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
,因为存储项目的顺序很重要。谢谢我为什么用它。感谢您的深入解释,非常感谢!