`
stephen80
  • 浏览: 105593 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java immutability 不变性

    博客分类:
  • j2se
阅读更多
最近可能要写多线程程序,学写备忘,

<effective java > item 13
<java concurrency in practice> 3.4. Immutability


  谈优先选择不变类

不变类就是实例不能被改变的类, Effective Java 的 Item13 详细的探讨了为什么设计中要优先考虑将一个类设计为不变的,在细读后感觉平时自己的设计和这个观念有比较大的沟壑,值得总结一下这个 item ,并反思一下如何去实践这个 best practice 。

不变类的优点有如下几个:容易设计,实现和使用,不易出错,安全性更好。

不变类很简单,它只会有一个状态,所以一旦在实例化的时候保证了这个不变实例复合某些业务逻辑上的要求,它就会一直,保持这些要求和规约得到满足。而一个可变类,则相对来说不可靠得多。

不变类是线程安全的,不需要考虑同步的问题,可以安全地共享。同时也不需要在共享过程中的传递引用环节使用“防御性复制”( item24 详谈,主要是保持数据的复制而不是引用的复制)。

由于不变类的上述优点,使得它非常适合成为其他类的组成部分,如果你明确了一个组件是不变类,则能在维护整体的业务逻辑稳定性方面轻松很多。非常显著的一个例子就是用于 map 的 keys 和 set 的 elements 时,不变类的稳定性保证了数据不会不小心被改变。反之,如果是用可变类, key 对象的一次逻辑上不恰当的变动(语法上无错,可以通过编译)可能导致另一处代码在 map 中获取 elements 时找到不正确的值,而实际经验中,我们深刻体会到的一件事情就是不被编译器发现而且不抛出异常的程序错误往往会浪费极大的精力,而且要靠好的视力和丰富的调试经验才能发现。

不变类的唯一缺点就是对应每个不同的值,必须存在一个单独的实例。当需要频繁变更值的时候,性能大为降低,典型的例子就是拿着 String 来反复折腾,而不用 StringBuffer 。而 StringBuffer 正是用来解决这一缺点的,当一个不变类可能需要频繁改变值的时候,就需要设计这么一个对应的可变类来暂时替身。

那么怎么在实际设计中贯彻这种优先选择不变类的思想呢,总的原则就是:除非你找到非常好的理由来设计为一个可变类,否则就应该设计为不变类,要有意的抵抗为每个变量配上 getter 和 setter 的冲动,当然我不是在说你要违反 javabean 的基本要求。。。基本上,小的存放数值的对象都应该设计为不变类,如果该类的值经常改,就配上对应的可变类。而总有些类显然不可能是不变类的,这时也要尽可能的限制它的可变性。类的构造器应该实例化一个充分满足逻辑不变式的实例,而不要交出一个半成品,也不应该提供构造器之外的一个所谓的初始化方法,除非是有极好的理由。同理,也不要提供“重设初始化”方法以达到实例复用的目的,比起它带来的危害,这个垃圾回收环保复用的思路带来的性能提升实在微不足道。



最后,归纳一下设计不变类的 5 条规则:

1.       不提供任何修改对象的方法。

2.       保证没有任何一个方法会被覆盖。

3.       所有的域都是 final 的。

4.       所有的域都是 private 的。

5.       如果不变类内部包括可变的子对象,保证它绝对不会被其他代码获取引用。



要解释的是第 5 ,第 4 点并不能保证这一点,要做到第 5 点,就必须注意在不变类的实例化中,决不通过其他代码提供的引用来赋值给这个子对象,也决不提供这个子对象的引用的获取方法,因为这些传入传出的引用在别的代码中可以被用来修改对象的域。在构造器,读取方法中使用防御性复制,只传值,不传引用。而且是递归性的防御性复制,关于这一话题,在以后的随笔中再详细探讨。

好了,这一篇就到这里,我从中学到的东西,总结起来一句话,就是要非常吝啬类的可变性,从而获取坚固,不易错的类结构。
分享到:
评论

相关推荐

    string-immutability:Java字符串不变性和StringBuilder不变性的单元测试。 String和StringBuilder是两个与文本处理相关的流行类

    在`string-immutability-master`这个项目中,可能包含了这样的测试用例,通过Junit或其他测试框架,来演示和验证Java字符串不变性以及`StringBuilder`的可变性。测试代码通常会包括创建、修改和比较字符串的不同方法...

    Java并发编程实践(java concurrency in practice)pdf (java多线程总结.ppt)

    书中讨论了线程安全的层次,如不变性(Immutability)、可重入(Reentrancy)、可预测性(Predictable)和无状态(Statelessness)。 4. **并发工具类**:Java 5及更高版本引入了`java.util.concurrent`包,包含...

    三张图彻底了解Java中字符串的不变性

    在Java编程语言中,字符串的不变性(Immutability)是一个关键特性,它指的是字符串对象一旦创建后,其内容就不能被修改。这个概念对于理解和优化Java程序至关重要,尤其是在处理字符串操作时。以下将通过三张图来...

    transit-java-0.8.269.zip

    yaidom是"Yet Another Immutable DOM"的缩写,它是一个用Java编写的XML DOM实现,强调不变性(immutability)和灵活性。不变性意味着一旦创建了XML文档对象,就不能再对其进行修改,这有助于代码的并发处理和调试,...

    Java_SE应用部分-34

    在Java编程中,`String`类作为最基础的字符串处理工具,一旦创建,其内容便不可更改,这主要是为了确保数据的不变性(Immutability)。然而,当遇到需要频繁修改字符串内容的场景时,`StringBuffer`类便显得尤为重要...

    8张图解java

    #### 一、字符串不变性(String Immutability) 字符串在Java中是不可变的对象。一旦创建了一个字符串对象,其内容就不能改变。这种特性对于字符串非常重要,因为它提高了程序的安全性和效率。 **示例代码解析:**...

    scala in depth电子书

    书中强调了不变性(Immutability),即创建不可变的数据结构,这有助于构建线程安全的程序。此外,还探讨了Scala中的并发模型和模式,为编写并发程序提供指导。 在风格和编码习惯方面,本书推荐使用有意义的变量...

    String总概况及其特性并与StringBuffer的区别详解

    - **哈希码一致性**:`String`的不可变性确保了其哈希码在对象生命周期内保持不变,这对于散列表如`HashMap`来说非常重要。 2. **创建方式** - 可以通过字面量的方式创建`String`对象,例如`String str = "abc";`...

    credit-card-validator:简单的Clojure信用卡验证程序

    Clojure是一种现代的、动态的、基于Lisp的函数式编程语言,运行在Java虚拟机(JVM)上。 首先,我们要理解Clojure的基本特性。Clojure强调 immutability(不可变性),这使得代码更易于理解和调试,因为数据一旦...

Global site tag (gtag.js) - Google Analytics