为什么共享不可变对象的可变内部结构是个好主意?
Why is sharing the mutable internals of immutable objects a good idea?
我正在阅读 Joshua Bloch 的 "Effective Java",有两个问题。布洛赫陈述如下。
Not only can you share immutable objects, but they can share their internals.
然后他继续给出一个例子,其中 BigInteger
的一个实例与另一个 BigInteger
实例共享其幅度数组。我的第一个问题是:这是否违反了 Bloch 之前制定的规则,即
Ensure exclusive access to mutable components.
作为共享可变内部结构如何成为问题的示例,在我看来,如果相同 class 的两个实例 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}
。
因此,我的第二个问题是:在实例之间共享可变内部结构不会破坏不变性吗?
共享不可变对象的内部结构很好,前提是您以不可变的方式公开对象的内部结构。
例如:
public class ImmutableObj {
private final String[] internals;
public ImmutableObj(String[] strings) {
internals = Arrays.copyOf(strings, strings.length);
}
public String[] getInternals() {
// return a copy of the internal state, since arrays
// do not offer an immutable view
return Arrays.copyOf(internals, internals.length);
}
}
数组是一个低效的例子,但它仍然是可能的。一个更高效的事情是 storing/exposing 内部状态作为某种 Collection<String>
所以你可以将内部设置为一个不可修改的对象开始:
public class ImmutableObj {
// Simply make this public instead of getter since it is read-only
public final List<String> internals;
public ImmutableObj(String[] strings) {
internals = Collections.unmodifiableList(Arrays.asList(strings));
}
}
我正在阅读 Joshua Bloch 的 "Effective Java",有两个问题。布洛赫陈述如下。
Not only can you share immutable objects, but they can share their internals.
然后他继续给出一个例子,其中 BigInteger
的一个实例与另一个 BigInteger
实例共享其幅度数组。我的第一个问题是:这是否违反了 Bloch 之前制定的规则,即
Ensure exclusive access to mutable components.
作为共享可变内部结构如何成为问题的示例,在我看来,如果相同 class 的两个实例 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}
。
因此,我的第二个问题是:在实例之间共享可变内部结构不会破坏不变性吗?
共享不可变对象的内部结构很好,前提是您以不可变的方式公开对象的内部结构。
例如:
public class ImmutableObj {
private final String[] internals;
public ImmutableObj(String[] strings) {
internals = Arrays.copyOf(strings, strings.length);
}
public String[] getInternals() {
// return a copy of the internal state, since arrays
// do not offer an immutable view
return Arrays.copyOf(internals, internals.length);
}
}
数组是一个低效的例子,但它仍然是可能的。一个更高效的事情是 storing/exposing 内部状态作为某种 Collection<String>
所以你可以将内部设置为一个不可修改的对象开始:
public class ImmutableObj {
// Simply make this public instead of getter since it is read-only
public final List<String> internals;
public ImmutableObj(String[] strings) {
internals = Collections.unmodifiableList(Arrays.asList(strings));
}
}