以下类是不可变的:
final class MyClass {
private final int[] array;
public MyClass(int[] array){
this.array = array;
}
}
答案 0 :(得分:21)
不,不是因为数组的元素仍然可以更改。
int[] v1 = new int[10];
MyClass v2 = new MyClass(v1);
v1[0] = 42; // mutation visible to MyClass1
答案 1 :(得分:6)
关于不变性规则的两分钱(我从阅读有效Java中保留了这一规定!):
答案 2 :(得分:1)
“不变性”是程序员和他自己之间的惯例。该规范可能或多或少地由编译器强制执行。
如果类的实例在应用程序代码执行的正常过程中没有更改,则它们是“不可变的”。在某些情况下,我们知道它们不会改变,因为代码实际上禁止它;在其他情况下,这只是我们如何使用该类的一部分。例如,java.util.Date
实例是正式可变的(它上面有一个setTime()
方法)但是习惯上将它处理为就像它是不可变的一样;这只是一个应用程序范围的约定,Date.setTime()
方法不会被调用。
作为补充说明:
String
被记录为不可变的(这就是Javadoc所说的)。但是,如果查看源代码,您将看到String
实例包含一个名为hash
的私有字段,该字段可能会随时间而变化:这是hashCode()
返回的值的缓存。我们仍然说String
是不可变的,因为hash
字段是内部优化,从外部看不到任何效果。final
的字段)。并不是说这是一个好主意:它可能会破坏使用所述实例的其他代码段所使用的假设。正如我所说,不变性是一个惯例:如果程序员想要自己打,那么他可以,但这会对生产力产生不利的副作用...... MyClass
实例的不变性?这个问题没有通用答案。答案 3 :(得分:0)
无法使数组成为不可变的。也就是说,没有办法阻止任何客户端代码设置或删除或添加项目到数组。
这是一个真正不可改变的选择:
private static class MyClass
{
private List<Integer> list;
private MyClass(final int[] array)
{
final List<Integer> tmplist = new ArrayList<Integer>(array.length);
for (int i : array)
{
tmplist.add(array[i]);
}
this.list = Collections.unmodifiableList(tmplist);
}
}
答案 4 :(得分:0)
要使类不可变,您需要确保其上的所有字段都是最终的,并且这些字段的类型也是不可变的。
这可能是一件难以忘怀的事,但有一种工具可以帮助你。
Pure4J提供了注释@ImmutableValue
,您可以将其添加到界面或类中。
有一个maven插件可以在编译时检查你是否符合此后的不变性规则。
希望这有帮助。