【发布时间】:2019-02-10 20:37:38
【问题描述】:
我正在阅读 Joshua Bloch 的“Effective Java”并有两个问题。布洛赫陈述如下。
您不仅可以共享不可变对象,还可以共享其内部。
然后他继续举一个例子,BigInteger 的一个实例与另一个BigInteger 实例共享其幅度数组。我的第一个问题是:这是否违反了布洛赫之前提出的规则,即
确保对可变组件的独占访问。
作为共享可变内部结构可能存在问题的一个示例,在我看来,如果同一类的两个实例 sample1 和 sample2 可以共享它们的内部结构,那么您可以拥有以下内容。
public final class Sample {
private final int[] field1;
private final int[] field2;
public Sample(int[] field1, int[] field2) {
this.field1 = field2;
this.field2 = field2;
}
public Sample(int[] field1, Sample sampleForField2) {
this.field1 = field1;
for (int i = 0; i < sampleForField2.field2.length; i++) {
sampleForField2.field2[i] += 1;
}
this.field2 = sampleForField2.field2;
}
public static void main(String[] args) {
Sample sample1 = new Sample(new int[]{0, 1}, new int[]{10, 11});
Sample sample2 = new Sample(new int[]{20, 21}, sample1);
System.out.println(Arrays.toString(sample1.field2));
}
}
在上面的示例中,a 能够通过构造函数public Sample(int[] field1, Sample sampleForField2) 与b 共享其内部结构。这会导致混叠,导致sample1 的field2 值为{11, 12}。
因此,我的第二个问题是:在实例之间共享可变内部不会破坏不变性吗?
【问题讨论】:
-
在我看来,共享不可变对象的可变内部并不是一个好主意。唯一的例外是,如果你能以某种方式保证两个实例都不会改变它的任何可变组件(这可能是 Josh 的意思)。这里的问题是,在 Java 中,您不能对数组之类的东西强制执行不变性。
-
BigInteger 是不可变的。所以它的内部幅度数组永远不会改变。因此,与另一个保证永远不会改变其大小的不可变 Integer 共享它不是问题。 BigInteger 不与未知物体共享其大小。它与 BigInteger 的其他实例共享它,从而保证量级的不变性。
-
JB 说的是对的。尽管内部数组是“可变的”,但它实际上从未改变。这意味着它确实是不可变的(结合 Java 中关于同步和发生前发生的其他一些规则)。因此,即使“可变内部”看起来是可变的,但实际上并非如此。这就是为什么可以分享的原因。
标签: java immutability effective-java