Record in Java 文档中"shallowly immutable"的含义 14

Meaning of "shallowly immutable" in the documentation of Record in Java 14

我正在阅读 Records 的文档 并且不理解 "shallowly immutable" 这个词。 浅度不可变 是什么意思? 如果它是不可变的,为什么我们需要一个复制构造函数?为什么是两个 "Hello Worlds!"?

对于所有记录类,以下不变量必须成立:如果记录R的组件是c1,c2,... cn,那么如果记录实例被复制如下:

 R copy = new R(r.c1(), r.c2(), ..., r.cn());  // copy constructor ?

那么一定是r.equals(copy).

浅不可变意味着,如果 class 有字段,这些字段将被视为 final。但是,他们的字段(即字段的字段)不需要是final.

您不需要实现构造函数,它已经以这种方式为您实现了。但是如果你选择自己实现它,例如对于参数验证,那么这个不变量应该成立。

如果您将 class 视为其他 classes 和基元(整数、数组等)的组合或层次结构,则浅层不变性指的是只是第一级。

它与术语'deep immutability'相反,它指的是整个层次结构的不变性。您听到的关于不可变性的大部分有形好处,例如隐式线程安全,仅适用于深度不可变的东西。

考虑这个class

class Foo {
    private final MutableBar bar;

    //ctor, getter
}

这个 class 是浅层不可变的。不能直接改,可以间接改,比如

foo.getBar().setSomeProperty(5);

所以它不是深度不可变的。

浅不变性的另一个例子,只使用基元

class Foo {
    private final int[] ints;

    Foo(int[] ints) {
        this.ints = ints;
    }
}

这可以像这样变异

int[] ints = {1};
Foo foo = new Foo(ints);
ints[0] = 2;

对于较小的层次结构,有时使浅不可变 class 深不可变很简单。它通常涉及防御性副本,或将可变 classes 转换为不可变变体。

class Foo {
    private final int[] ints; 

    Foo(int[] ints) {
        // copy to protect against the kind of mutation shown above
        this.ints = Arrays.copyOf(ints, ints.length);
    }

    // if you must have a getter for an array, make sure not to return the array itself, 
    // otherwise the caller can change it.
    // for performance reasons, consider an immutable List instead - no copy required
    int[] getInts() {
        return Arrays.copyOf(ints, ints.length);
    }
}