Java 作为成员变量的不可变类中的对象

Java 作为成员变量的不可变类中的对象,java,immutability,Java,Immutability,我有一个类X,它保存Employee对象。我想使类X不可变。现在,即使我将Employee对象声明为final,Employee类也独立存在,人们可以访问特定Employee对象的setter方法。是否可能有一个普通的类Employee和另一个不可变的类X,其中包含Employee,但一旦分配了Employee,我们就不能更改它的值 public final class X { private final Employee emp; public X (Employee e){ thi

我有一个类X,它保存Employee对象。我想使类X不可变。现在,即使我将Employee对象声明为final,Employee类也独立存在,人们可以访问特定Employee对象的setter方法。是否可能有一个普通的类Employee和另一个不可变的类X,其中包含Employee,但一旦分配了Employee,我们就不能更改它的值

public final class X {

private final Employee emp;

public X (Employee e){
   this.emp = e;

}
public Employee getEmp(){

return emp;

}

} 
employee类我不想使其不可变,只想使类X不可变。因此,一旦员工被分配,就不应该允许更改它。 在不使类Employee不可变的情况下,这是可能的。
我希望班上的员工能够独立存在,所以不想将其建筑私有化

不必公开不可变类的Employee成员。您可以引入只公开员工相关字段的getter方法

public final class X {

  private final Employee emp;

  public X (Employee e){
     this.emp = e.clone ();
  }

  public String getEmpName(){
    return emp.getName();
  }

  public int getEmpSalary(){
    return emp.getSalary();
  }

} 

当然,还要做一件事来确保类是真正不可变的。构造函数应该创建传递给它的员工的副本。否则,构造函数的调用方仍将拥有对Employee的引用,并且可以更改该对象。

您不必公开不可变类的Employee成员。您可以引入只公开员工相关字段的getter方法

public final class X {

  private final Employee emp;

  public X (Employee e){
     this.emp = e.clone ();
  }

  public String getEmpName(){
    return emp.getName();
  }

  public int getEmpSalary(){
    return emp.getSalary();
  }

} 

当然,还要做一件事来确保类是真正不可变的。构造函数应该创建传递给它的员工的副本。否则,构造函数的调用方仍将有对Employee的引用,并且可以更改该对象。

您可以向Employee添加一个副本构造函数,并在其实例传入或传出不可变类时使用它

public final class X {

    private final Employee emp;

    public X (Employee e){
       this.emp = new Employee(e);

    }
    public Employee getEmp(){
      return new Employee(emp);
    } 
} 

话虽如此,您仍然应该认真地重新评估是否最好也使Employee不可变,因为所有这些复制可能会有相当大的开销。

您可以向Employee添加一个复制构造函数,并在Employee的实例传入或传出不可变类时使用它

public final class X {

    private final Employee emp;

    public X (Employee e){
       this.emp = new Employee(e);

    }
    public Employee getEmp(){
      return new Employee(emp);
    } 
} 

话虽如此,您仍然应该认真地重新评估是否最好也使员工不可变,因为所有这些复制可能会有相当大的开销。

其他人理论上仍然可以更改通过构造函数提交的实例,因此这不是100%安全的解决方案Hey Eran,现在一切都有意义了。谢谢你的信息。因此,如果我不返回带有emp对象的用户,他将无法进行任何修改。其他人理论上仍然可以更改通过构造函数提交的实例,因此这不是100%安全的解决方案。嘿,Eran,现在一切都有意义了。谢谢你的信息。因此,如果我不返回带有emp对象的用户,他将无法进行任何修改。也感谢您提供此选项。我只是对这个设计很好奇。如果我需要实现它,我会记住你说过的话。同样感谢你的选择。我只是对这个设计很好奇。如果我需要实施它,我会记住你说过的话。