我怎样才能使这个对象变得可变

2 java mutable immutability

我有这个简单的不可变对象:

public class Alt {
public LinkedList<Integer> list = new LinkedList<Integer>();

public void refresh() {
    Random rand = new Random();

    list.clear();

    for (int i = 0; i < 50; i++) {
        list.add(rand.nextInt(32));
    }
}

public void compare(Alt alt) {
    for (int i = 0; i < list.size(); i++) {
        System.out.println(alt.list.get(i) + " " + list.get(i));
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

但是这个类是一个不可变对象,例如当我运行时:

Alt a = new Alt();
a.refresh();
Alt b = a;
b.refresh();

a.compare(b);
Run Code Online (Sandbox Code Playgroud)

返回的值是相同的,对象b就像是对象a的快捷方式,并且或多或少是重复的.有没有办法让它分开?或者我是以完全错误的方式做到这一点.

Hoo*_*pje 6

你的术语是错的.这不是一个不可变的对象.该refresh()方法修改了对象.在下面的代码中将输出两行不同的行:

Alt a = new Alt();
a.refresh();
System.out.println(a.list);
a.refresh();
System.out.println(a.list);
Run Code Online (Sandbox Code Playgroud)

此外,因为该字段list是从类外部可见的,所以可以直接修改它:

Alt a = new Alt();
a.refresh();
System.out.println(a.list);
a.list.set(10, 42);
System.out.println(a.list);
Run Code Online (Sandbox Code Playgroud)

您观察到的行为是由a = b不创建对象的新副本的事实引起的.它仅使引用 b指向与引用相同的对象a.由于只有一个对象,因此a.compare(b)将两次打印相同的数字.

要制作对象的副本,您必须自己编程.在Java中,这通常由所谓的复制构造函数完成:

public Alt(Alt original) {
    list = new LinkedList<>(original.list);
}
Run Code Online (Sandbox Code Playgroud)

(注意该复制构造函数如何调用复制构造函数LinkedList,它构成了列表的副本.)

现在你可以写:

b = new Alt(a);
Run Code Online (Sandbox Code Playgroud)

然后b将引用恰好包含相同数据的新对象.