一般来说,我在Java中使用不可变对象的次数越多,我认为它们就越好。它们具有很多优点,从自动线程安全到不需要担心克隆或复制构造函数。
这让我想到,一个“不可变”的关键词会不会出错?显然,在语言中加入另一个保留字是有缺点的,我怀疑它实际上主要是出于上述原因 - 但忽略了我不能真正看到很多缺点。
目前必须非常小心地确保对象是不可变的,即使这样,声称组件对象的狡猾的javadoc注释也是不可变的,而事实上它并不能破坏整个事物。还有一种观点认为,即使像字符串这样的基本对象也不是真正不可变的,因为它们很容易受到反射攻击的影响。
如果我们有一个不可变的关键字,编译器肯定可以递归地检查并给出一个铁壳保证,即类的所有实例都是不可变的,这是目前无法完成的。特别是随着并发性越来越多的使用,我个人认为在这种效果中添加关键字会很好。但是,我有什么缺点或实施细节,这使得这个想法很糟糕吗?
答案 0 :(得分:4)
通常,不可变对象应优先于有状态对象,it's currently fairly difficult to make an immutable object in Java。实际上,大多数OO语言对不可变对象的支持很少,而大多数函数式语言都认为它们是理所当然的,例如F#,Haskell和Clojure。
向Java添加不可变关键字可以生成代码......
final
和private
,没有意外添加使类可变的方法,也可能没有手动标记类final
(subclasses can add mutable state)。new ImmutableFoo(1, 2, 3)
都必须创建一个新对象,除非编译器能够证明您的类不能被变异。如果ImmutableFoo
标有immutable
关键字,则每个此类调用都可以返回相同的对象。我很确定new
必须总是创建一个新对象,这使得这一点无效,但与编译器的有效通信仍然是一件好事。Scala's case classes are similar to an immutable keyword. C# 5中也考虑了不可变关键字。
答案 1 :(得分:4)
虽然使所有字段最终并且还验证任何类引用也是不可变的,但是在其他情况下这是不可能的。
如果您的最终课程还包含一些延迟加载的字段,该怎么办? 人们需要进一步支持将这些字段标记为不可变和懒惰。
看一下java.lang.String及其chars []数组,编译器怎么能真正知道它是不可变的?每个人都知道字符串,但另一个类似的类可以很容易地包含一个更新数组的方法。进一步的支持需要验证一旦设置了字段,没有其他指令可以“写”到数组。不久之后,这将成为一个非常复杂的问题。
最后任何这样的关键字如果确实有效可能会有所帮助,但它仍然不意味着程序更好。优秀编码器的良好设计意味着更好的结果。即使平台限制了一些陷阱,哑巴编码员仍然可以写垃圾。
答案 2 :(得分:1)
我非常喜欢不变性,所以在我看来,绝对是。 OO编程中不变性的优点是无数的,它不应该只是函数式编程语言的领域。
答案 3 :(得分:1)