Java中的不可变类
根据许多文档,我已经看到不可变类应该具有以下特性:Java中的不可变类,java,class,immutability,final,Java,Class,Immutability,Final,根据许多文档,我已经看到不可变类应该具有以下特性: 课程应该是期末考试 所有的方法都应该是最终的 所有的变量都应该是最终的 不应该有任何二传手 但我的问题是: 如果我有一个只有最终变量的类呢 如果我也有setter,我就不能改变对象的状态,因为我有所有的最终变量。那么这将如何影响不变性呢 在这种情况下,继承如何更改对象状态 1.如果我有一个只有final变量的类怎么办 这会让你走得更远,但不是一路走来。这些变量的类型也需要是不可变的。例如考虑< /P> class MyImmutableClas
final
变量的类怎么办
这会让你走得更远,但不是一路走来。这些变量的类型也需要是不可变的。例如考虑< /P>
class MyImmutableClass {
// final variable, referring to a mutable type
final String[] arr = { "hello" };
// ...
}
这允许某人做某事
myImmutableObject.arr[0] = "world";
并有效地改变不可变类的对象
此外,建议禁止扩展类(因为没有办法强制子类是不可变的)。请参阅下面第三个问题的答案
动物
被狗
子类,并且狗
有一个变异对象的setDogsName
方法,那么实际上您可能有实际上是可变的动物
对象(类型狗
)
换句话说,如果一个不可变的类开放进行扩展,那么不可变性的大部分(全部?)好处就失去了:例如,如果您收到一个Animal
作为方法的参数,您就不能假定它是不可变的。你不能安全地将Animal
对象作为键放在散列图中,等等
基本上,原始语句有点多余,这就是为什么我认为它们有点令人困惑的原因:
- 不能扩展
类,因此将方法标记为final
final
- 如果所有变量都是最终的,那么说不应该有设置器是多余的
final
位于参考级别,而不变性位于实例级别
在上面的代码中。如果没有引用列表,则任何人都可以执行以下操作:
someList.add(someValue)
但他们无法做到:
someList=someOtherList;
这就是区别
在这种情况下,继承如何更改对象状态
子类可以访问父类的某些字段,然后对其进行更改。可以使父类引用点指向子类对象并修改其字段。因此,为了确保不变性,您必须确保子类不会改变父类中的任何内容。所以,让它成为最终的,一个不可变的类是你不能改变的。实现不变性就是消除改变对象状态的可能方式。这可以通过结构和行为手段的结合来实现
但首先,让我们看看“应该拥有”列表:
- “课程应该是最终的”-这可能是可取的,但可能不是严格必要的。。。甚至是令人渴望的。即使某些子类的实例是可变的,类的实例1也可以是不可变的。这完全取决于哪些类需要是不可变的,这取决于上下文
- “所有的方法都应该是最终的”——既不必要也不充分。如果该类为
,则不需要该类。如果该类不是final
,则它是不够的。(您可以在子类中添加具有不同签名的方法。)final
- “所有变量都应该是最终的”-既不必要也不充分。您可以有一个字段不是
的不可变类,以及一个字段都是final
的可变类final
- “不应该有任何setter”-这取决于你所说的“setter”是什么意思,但再一次,这既不是必要的(对于某些可变模型),也不是充分的
你的问题: 1) 如果我有一个只有最终变量的类呢 这不足以保证不变性。例如,如果最后一个变量之一是数组,则可以更改该数组的状态,从而更改整个对象的状态。这可以由setter(或该类的任何其他方法)完成,或者如果该类是“泄漏抽象”,则可以由外部代码完成 2) 如果我也有setter,我就不能改变对象的状态,因为我有所有的最终变量。那么这将如何影响不变性呢 见上文。将所有字段声明为
final
并不能保证不变性。setter可以更改对象的可变组件的状态
3) 在这种情况下,继承如何更改对象状态
不可能。但这不是重点
创建不可变类final
的原因是为了阻止某人创建该类的可变子类
这有什么关系
好吧,假设一个方法要求参数是不可变的(例如为了安全)。如果您用一个不可变的类声明它
someList=someOtherList;