技术开发 频道

JAVA:实现非可变的重要性

  【IT168 技术】Java Zone与AppDynamics合作为你呈现。你会发现AppDynamics如何一步步提升你的游戏性能,使您的企业避免被这些排名前十的Java性能问题影响。Java的一致的批评之一是它缺少一个正式的不可变类型。我们可以(而且应该)在创建不可变对象上做一个好的尝试,尽管他们可能由于JVM的性质而存在固有的缺陷。

                         JAVA:实现非可变的重要性

  一个不可变对象指的是一个在初始化创建之后状态不能、也不会改变的对象。不可变对象是非常好的,主要是因为它们是线程安全的(并且线程的代码应该尽可能避免)。你可以经过它们而不用担心他们会被改变。我强烈建议你花一些时间在函数式语言比如Scala上去欣赏不可变对象拥有的神奇力量 (然后直接返回,因为Scala的包完全不同)。

  有趣的是,在Java 8中,几乎所有的新特性(日期和时间,可选和流)一直以不可变的方式实现。这使得大部分的性能优势,可以来自诸如并行流。不可变对象允许我们在功能性编程语言中创建无副作用的功能是创建快速开源代码的基础。

  如何在Java中创建一个不可变的对象?

  主要作用是将所有字段标记出来作为最终版。这显然意味着他们在初始化构建之后不能更改。要注意,你仍然可以拥有一个所包含的对象是可变的最终领域。在这种情况下初始化构建对象时很有必要复制一下对象,并且从外部类存取时提供复制对象。

  这显然增加了我们的编码和设计的难度。理念上你应该遵循Java原始有效的建议:

  “类应该是不变的,除非有一个很好的理由让他们可变....如果一个类不能是一成不变的,尽可能地限制其可变性。”

  如果你的类中有一个对象域,你也应该尽可能地使它不可变。

  如果你成功地使所有得字段不可变,那么你也可以选择让他们是公有的,就像我一样——字段不可以被改变仅可以用于阅读。这增加了getter冗余。在我的代码库中,如果我使用字段访问数据那么我将知道类是不可变的。最大的例外是当我写库时,因为如果之后你需要介绍可变性它很难于重构。如果你拥有所有的代码,从字段访问到IntelliJ不过是访问一个快捷方式。

  你也应该让你的类最终防止子类化。它可能会创建可变的子类,进而毁了你的辛勤工作。

  创建不可变类需要自己有意识的努力,但它应该尽可能成为你的目标。我见过在开发人员中普遍的的反面模式是在创建一个构造函数和生成字段之后,他们都会生成getter /或者setter。千万不要这样做!首先,编码只能在有需要时编写,如果你没有编译或运行的访问字段的代码,它不需getter;;如果创建后没有任何代码试图改变其他字段,你不需要setter。按需求编码并且不需要过早优化。

  不可变对象最主要的缺点是它会导致对象扩散并最终导致性能出现问题——大量的生产有潜力的新对象, 为了任意改变状态你必须创建一个新的。除非你处于疯狂的高性能环境下(你几乎不会这样),否则它真的不是一个问题。对象是廉价的。甲骨文这样认为:

  “对象创建的影响往往是被高估了,它可以被一些有效的,与不可变对象的关联所抵消。由于垃圾收集,其中包括减少开销和消除需要被保护以免变体的可变对象的代码。”

  这是一个典型的紧急代码优化。如果你创建不可变的代码,结果将证明你正在攻克巨大的性能障碍---重构。在大多数情况下你是没事的。也有一些明显的例外:数据结构往往是更容易实现,并且如果使用可变性会有更好的性能。一如既往地将常识应用到你的方法中,但是默认是不变的。

  Java Zone与AppDynamics合作为你呈现。AppDynamics帮助你获得应用程序的性能和非常好的实践背后的基本原理,这样你就能主动分析它们表现出的性能问题,以及其他更具体地有关你的Java应用程序。

  原文链接:https://dzone.com/articles/the-importance-of-immutability-in-java

0
相关文章