Java:复合对象的不变性
假设我有一个定义如下的Employee类:Java:复合对象的不变性,java,Java,假设我有一个定义如下的Employee类: class Employee { private final String id; private final String name; private final String dept; private final Address address; public Employee(String id, String name, String dept, Address address) { this.id =
class Employee {
private final String id;
private final String name;
private final String dept;
private final Address address;
public Employee(String id, String name, String dept, Address address) {
this.id = id;
this.name = name;
this.dept = dept;
this.address = address;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDept() {
return dept;
}
public Address getAddress() {
return address;
}
}
class Address {
private String addrLine1;
private String addrLine2;
...
}
在上面的代码中,如果Address对象可以用setter更改,Employee真的是不可变的吗?如果不是,我们是否应该克隆()Employee以返回原始Employee?..如果它的状态是可变的,它不是不可变的如果返回的对象是可变的,则第一个对象引用数据也将更改
正如您所说,只需返回一个安全副本。如果它的状态是可变的,它不是不可变的如果返回的对象是可变的,则第一个对象引用数据也将更改
正如您所说,只需返回一份安全副本。如果您的
地址
类具有使其可变的setter,那么不,我会说员工
不是不可变的,因为它包含的地址可以更改。如果您的地址
类具有使其可变的setter,那么不,我认为Employee
不是不可变的,因为它包含的地址可以更改。您需要克隆()可变对象,即address。克隆雇员没有帮助。您需要克隆()可变对象,即地址。克隆Employee不会有帮助。您应该确保在存储任何可变字段之前对其进行克隆,并在getter中返回时进行克隆。
在构造函数中:
this.address = address.clone();
在你的getter中:
return address.clone();
这样,除此Employee对象外,没有其他对象可以访问Address对象的位置。您应该确保在存储任何可变字段之前对其进行克隆,并在getter中返回时对其进行克隆。 在构造函数中:
this.address = address.clone();
在你的getter中:
return address.clone();
通过这种方式,除了这个Employee对象之外,没有其他对象可以访问address对象的位置。这取决于您在不变性中想要什么:如果您希望它意味着对象的整个图形不会改变,那么显然,拥有一个可变地址是无法实现这一点的 我想,你可以将这种“深”不变性称为“浅”不变性 提供一个
@ImmutableValue
注释(以及用于编译时检查代码的相关maven插件),以确保当您希望某些内容是深度不可变的时,它实际上是不可变的
免责声明:我是这个库的开发者
但是,我希望它对某些人有用。这取决于你想要什么样的不变性:如果你想让它意味着对象的整个图形不会改变,那么显然,拥有一个可变地址是无法实现这一点的 我想,你可以将这种“深”不变性称为“浅”不变性 提供一个
@ImmutableValue
注释(以及用于编译时检查代码的相关maven插件),以确保当您希望某些内容是深度不可变的时,它实际上是不可变的
免责声明:我是这个库的开发者
但是,我希望它对某些人有用。您的代码不正确。属性地址声明为字符串,但getter返回地址。顺便说一句,这不是你要问的问题。既然它们是你问题的关键,你为什么要以上帝的名义把二传者排除在引用的代码之外@GuillaumePolet:关于地址的事情很正确,但是底部的那一点显然是个问题吗?这里还有第二个问题,
员工
是子类的,所以即使地址
不是,实例也可以变为可变的。@TJ抱歉,我不理解这个问题,因为在我看来,很明显,如果一个对象的属性是可变的,那么你的对象也是可变的。我保证不会再做了!你的代码不正确。属性地址声明为字符串,但getter返回地址。顺便说一句,这不是你要问的问题。既然它们是你问题的关键,你为什么要以上帝的名义把二传者排除在引用的代码之外@GuillaumePolet:关于地址的事情很正确,但是底部的那一点显然是个问题吗?这里还有第二个问题,员工
是子类的,所以即使地址
不是,实例也可以变为可变的。@TJ抱歉,我不理解这个问题,因为在我看来,很明显,如果一个对象的属性是可变的,那么你的对象也是可变的。我保证不会再做了!