Java中的不可变关键字是一个好主意吗?

时间:2011-01-13 00:30:35

标签: java immutability keyword

一般来说,我在Java中使用不可变对象的次数越多,我认为它们就越好。它们具有很多优点,从自动线程安全到不需要担心克隆或复制构造函数。

这让我想到,一个“不可变”的关键词会不会出错?显然,在语言中加入另一个保留字是有缺点的,我怀疑它实际上主要是出于上述原因 - 但忽略了我不能真正看到很多缺点。

目前必须非常小心地确保对象是不可变的,即使这样,声称组件对象的狡猾的javadoc注释也是不可变的,而事实上它并不能破坏整个事物。还有一种观点认为,即使像字符串这样的基本对象也不是真正不可变的,因为它们很容易受到反射攻击的影响。

如果我们有一个不可变的关键字,编译器肯定可以递归地检查并给出一个铁壳保证,即类的所有实例都是不可变的,这是目前无法完成的。特别是随着并发性越来越多的使用,我个人认为在这种效果中添加关键字会很好。但是,我有什么缺点或实施细节,这使得这个想法很糟糕吗?

4 个答案:

答案 0 :(得分:4)

通常,不可变对象应优先于有状态对象,it's currently fairly difficult to make an immutable object in Java。实际上,大多数OO语言对不可变对象的支持很少,而大多数函数式语言都认为它们是理所当然的,例如F#,Haskell和Clojure。

向Java添加不可变关键字可以生成代码......

  • 更容易写。没有弄乱finalprivate,没有意外添加使类可变的方法,也可能没有手动标记类finalsubclasses 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)

恕我直言,面向对象的框架(Java,.net等)应该包含更多的数组类型:可变数组,不可变数组,可变数组引用,不可变数组引用和只读数组引用(只读参考)可以指向一个可变或不可变的数组,但在任何情况下都不允许写入)。如果没有不可变的数组类型,很难以一种可以证明是不可变的方式构造许多有效的类型。