tangguo

不可变对象的所有属性都必须是最终的吗?

java

不可变对象是否必须具有所有属性final?

据我说不是。但是我不知道我是否正确。


阅读 385

收藏
2020-11-20

共1个答案

小编典典

不可变对象(所有属性都是final)和有效不可变对象(属性不是final,但不能更改)之间的主要区别是安全发布。

由于Java内存模型为最终字段提供了保证,因此您可以在多线程上下文中安全地发布不可变对象,而不必担心添加同步:

final字段还允许程序员无需同步即可实现线程安全的不可变对象。即使所有线程都使用数据竞争在线程之间传递对不可变对象的引用,线程安全的不可变对象也被所有线程视为不可变的。这可以提供安全保证,以防止由于错误或恶意代码而滥用不可变类。必须正确使用final字段以保证不变性。

附带说明,它还可以实现不可变性(如果由于忘记了它应该是不可变的而试图在类的将来版本中对那些字段进行突变,则不会编译)。

澄清说明

将对象的所有字段都设为final不会使其不变-您还需要确保(i)其状态不变(例如,如果对象包含final List,则没有任何突变操作(添加,删除… )必须在施工后完成),并且(ii)this在施工过程中不要让自己逃脱
一个有效不变的对象一旦安全发布便是线程安全的
不安全发布的示例:

class EffectivelyImmutable {
    static EffectivelyImmutable unsafe;
    private int i;
    public EffectivelyImmutable (int i) { this.i = i; }
    public int get() { return i; }
}

// in some thread
EffectivelyImmutable.unsafe = new EffectivelyImmutable(1);

//in some other thread
if (EffectivelyImmutable.unsafe != null
    && EffectivelyImmutable.unsafe.get() != 1)
    System.out.println("What???");

该程序理论上可以打印What???。如果i是最终决定,那将不是合法结果。

2020-11-20