当前位置: 首页 > 面试题库 >

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

申屠项明
2023-03-14
问题内容

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

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


问题答案:

不可变对象(所有属性都是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是最终决定,那将不是合法结果。



 类似资料:
  • 不可变对象的所有属性都必须是吗? 我会说他们没有。但是我不知道我是对是错。

  • 本文向大家介绍JavaScript变量Dom对象的所有属性,包括了JavaScript变量Dom对象的所有属性的使用技巧和注意事项,需要的朋友参考一下 DOM对象的HTML:   <button>Disable State</buttom> 1,遍历DOM对象所具有的属性(全部,不管是否在HTML tag中是否设置) 结果: 2.遍历DOM对象在HTML中设置过的属性:   每一个attribut

  • 问题内容: 这个问题已经在这里有了答案 : 为什么在匿名类中只能访问最终变量? (15个答案) 为什么实例变量“忽略Lambda表达式中使用的变量必须是最终变量或实际上是最终变量”警告[重复] (2个答案) Lambdas:局部变量不需要最终变量,实例变量不需要 (10个答案) 2年前关闭。 当我编写此代码时,我收到一个编译时错误,该错误是: “ lambda中的变量必须是final或有效的fin

  • 这肯定是个愚蠢的问题,但我对Kotlin真的是个新手,我没有找到任何解决办法。 如何声明类字段?就像我们可以在Java中拥有它一样: 在中: 但我得到一个警告:“属性必须初始化或抽象”

  • 如果属性值可以设置为 null,则其被认为是可选的(可空的)。相反,如果属性值设置为 null 是非法的,那么它就被认为是必须的属性。 惯例 按照惯例,值可以是 null 的运行时类型(string、int?、byte[] 等等)属性将被配置为可选。值不能为 null 的运行时类型(int、decimal、bool 等等)属性则将被配置为必须。 注意 值不能为 null 的运行时类型属性是无法被配

  • 问题内容: 例如,如果我有一个变量,并且在主线程中声明了一个runnable,并且想将x传递给该runnable的方法,则必须对其进行声明。为什么? 问题答案: 因为如果能够更改它们,可能会导致很多问题,请考虑以下事项: 这是一个粗略的示例,但您可以看到可能发生许多无法解释的错误。这就是变量必须为最终变量的原因。这是解决上述问题的简单方法: 如果您需要更完整的说明,则有点像同步。Java希望防止您