Java 使用不可变对象模拟特性更改
搜索后,我发现了这些问题,但没有找到我具体问题的答案: 以下是设置: 我有这样一个不可变的类:Java 使用不可变对象模拟特性更改,java,immutability,Java,Immutability,搜索后,我发现了这些问题,但没有找到我具体问题的答案: 以下是设置: 我有这样一个不可变的类: public class MyImmutableOb { private final String name; private final Collection<Integer> myNumbers; public MyImmutableOb(String name) { this.name = name; myNumber
public class MyImmutableOb {
private final String name;
private final Collection<Integer> myNumbers;
public MyImmutableOb(String name) {
this.name = name;
myNumbers = new LinkedList<>();
}
public MyImmutableOb(String name, MyImmutableOb oldOb) {
this.name = name;
myNumbers = new LinkedList<>();
for (int i : oldOb.getNumbers()) myNumbers.add(i);
}
public Collection<Integer> getNumbers() {
return new LinkedList<>(myNumbers);
}
}
我很难理解这个问题。正如您所发现的,为了使类的实例不可变,您必须明确地在类中写入不可变性;对象类型(与基元类型相反)本质上是可变的。
java.util
中的集合类当然是可变的。Java类,如String
和基本装箱类型Integer
、Double
等,被编写为不可变的
您的变量声明
private final String name;
private final Collection<int> myNumbers;
是不可变的,因为它被声明为final
,并且String
对象是不可变的
对变量使用final
关键字可以确保变量只能被赋值一次,因此它是设计不可变类的极好工具。但是,这还不够,因为如果变量被分配给可变对象,那么该对象中的变量仍然可以修改
您的变量声明
private final String name;
private final Collection<int> myNumbers;
因此,myNumbers
现在确实是不可变的。注意:我已经放弃了使用LinkedList
,因为当它在MyImmutableOb
中不可变时,使用专门的List
实现是没有意义的
这样,您的第二个构造函数就变成了
public MyImmutableOb(String name, MyImmutableOb oldOb) {
this.name = name;
this.myNumbers = oldOb.myNumbers;
}
因为oldOb
的myNumbers
已经是不可变的,所以复制没有意义
最后,我意识到在构建
MyImmutableOb
之后,您可能确实希望能够更改myNumbers
的内容。显然,使类真正不可变意味着在构建之后,其实例中没有任何内容可以更改。您的“不可变”类的myNumbers
成员是一个可变列表。您的类实际上是或不是不可变的。答案取决于类的//等…
部分中是否有任何内容修改列表。您的第二个构造函数调用oldOb.getNumbers()
,但您没有向我们显示getNumbers()的定义。它有什么作用?如果它只返回oldOb.myNumbers
,那么您的类是可变的:客户机可以调用getNumbers(),然后修改列表。这个定义可能会有所帮助,是吗?哈哈,我的错,我继续,并添加了定义。这些是当前类中所有的方法。是的,我看到你去掉了LinkedList
。为了澄清,使用了LinkedList
,因为存储项目的顺序很重要。谢谢我为什么用它。感谢您的深入解释,非常感谢!