Java中的强不变性与弱不变性?

Java中的强不变性与弱不变性?,java,Java,在我的Java访谈问答列表中,它说,在Java中,可以通过三种方式使对象不可变。其中一个方法是: 确保不能通过使类 final(强不变性)或使您的方法成为final(弱不变性) 不变性) 为什么将方法设置为final被认为比将类设置为final更不可变?另外,什么是强不变性和弱不变性?因为它表明,子类实例可以在任何需要超类实例的地方被替换,而不会从调用方的角度改变语义。子类可能会引入可变行为,从而违反LSP 一方面,final方法(和私有成员变量)限制了通过超类接口直接改变语义的范围。另一方面,

在我的Java访谈问答列表中,它说,在Java中,可以通过三种方式使对象不可变。其中一个方法是:

确保不能通过使类 final(强不变性)或使您的方法成为final(弱不变性) 不变性)

为什么将方法设置为final被认为比将类设置为final更不可变?另外,什么是强不变性和弱不变性?

因为它表明,子类实例可以在任何需要超类实例的地方被替换,而不会从调用方的角度改变语义。子类可能会引入可变行为,从而违反LSP

一方面,final方法(和私有成员变量)限制了通过超类接口直接改变语义的范围。另一方面,可变子类可以间接引入冲突


例如,基于不变性假设,调用方框架可能不会在多线程场景中进行克隆或使用同步。当应用于可变子类时,这将导致重大问题,但不是由于超类接口的任何语义更改。

使类成为final可确保您无法将其子类化,这意味着该类不可扩展。不变性不仅仅是保存对象的初始状态,而且是为了确保没有行为变化


但是,如果一个类没有标记为final,那么总是有可能将其子类化并更改其实现,我们知道父引用可以引用子对象。因此有可能违反不变性。

子类可能有可以更改的额外字段。请注意,在Java中,真正的不变性是不可能的,除非您承诺不在任何业务对象上使用
synchronized
,只在专用锁对象上使用。此外,还有第三种方法(类似于):您没有将类设置为final,但没有提供公共构造函数。@pbabcdefp虽然这是真的,但我不确定这是否真的是个问题。假设我们有
类A
,它是弱不可变的。我们创建了
类B扩展了一个具有新的可变字段的
。在像
A=new B()
这样的代码中,对于
A
引用,它的值仍然是不可变的,因为
B
无法更改
A
可以访问的任何内容(可能除了受保护的字段,但如果它们存在,我不确定
A
是否可以称为不可变)。我们确信
a
可以使用的所有方法都将具有相同的功能,因为这些方法是最终的。换句话说,
a
的可用范围仍然是不可变的。另一个问题是,如果对象
a
b
是不可变的,并且
a.equals(b)
,那么期望它们是可互换的是合理的。行为改变是可以的,只要行为也是不可变的。如果我们说行为是不可变的,那么它只是意味着它不应该改变。但不可变的是对象。