为什么共享不可变对象的可变内部是一个好主意?

时间:2019-02-10 20:37:39

标签: java immutability effective-java

我正在阅读Joshua Bloch的“有效Java”,并且有两个问题。 Bloch陈述以下内容。

  

您不仅可以共享不可变的对象,而且可以共享其内部。

然后,他继续给出一个示例,其中BigInteger的一个实例与另一个BigInteger实例共享其大小数组。我的第一个问题是:这是否违反了Bloch先前提出的规则,即

  

确保对可变组件的专有访问。

作为共享可变内部结构可能有问题的一个示例,在我看来,如果同一类的两个实例sample1sample2可以共享其内部结构,那么您可以得到以下内容。


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可以通过构造函数bpublic Sample(int[] field1, Sample sampleForField2)共享其内部。这会导致混叠,导致sample1的{​​{1}}值为field2

因此,我的第二个问题是:实例之间共享可变的内部结构不会破坏不变性吗?

1 个答案:

答案 0 :(得分:0)

如果您以不可变的方式公开对象的内部,则可以共享不可变对象的内部。

例如:

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);
  }
}

数组是一个低效率的示例,但仍然可以实现。更具表现力的事情是将内部状态存储/公开为某种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));
  }

}