在Java 14中Record文档中 "浅层不可变 "的含义。

问题描述 投票:1回答:1

我正在阅读以下文件 记录并不理解 "浅尝辄止 "这个词。什么叫 浅尝辄止? 如果它是不可变的,为什么我们需要一个复制构造函数?为什么要有两个 "Hello Worlds!"?

对于所有的记录类,以下的不变性必须成立:如果一个记录R的成分是c1,c2,......cn,那么如果一个记录实例被复制成如下的样子。

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

那么一定是这样的情况: r.equals(copy).

java record
1个回答
24
投票

Shallowly immutable的意思是,如果一个类有字段,这些字段就会被看作是: final. 然而, 字段(即字段的字段)不需要是 final.

你不需要实现一个构造函数,它已经为你实现了。但是如果你选择自己实现它,例如为了参数验证,那么这个不变性应该成立。


10
投票

如果你把一个类看作是其他类和基元(ints、数组等)的复合体或层次结构,那么浅层不变性指的是仅仅是第一层的不变性(不变性)。

它与 "深层不变性 "一词相反,后者指的是整个层次结构的不变性。你所听到的关于不可变性的大多数有形的好处,比如隐含的线程安全,只适用于深不可变的东西。

考虑一下这个类

class Foo {
    private final MutableBar bar;

    //ctor, getter
}

这个类是浅层次的不可变的。它不能直接改变,但可以间接改变,比如说

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 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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.