3 回答
TA贡献1810条经验 获得超4个赞
不可变对象(所有属性都是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是最终决定,那将不是合法结果。
TA贡献1946条经验 获得超3个赞
不可变=不可更改。因此,使属性最终确定是一个好主意。如果没有保护对象的所有属性不被更改,我不会说对象是不可变的。
但是如果对象的私有属性未提供任何设置方法,则该对象也是不可变的。
添加回答
举报