快速业务通道

Java理论与实践: 变还是不变? - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-22

Java理论与实践: 变还是不变?

时间:2010-12-21 IBM Brian Goetz

不变对象是指在实例化后其外部可见状态无法更改的对象。Java 类库中的 String 、 Integer 和 BigDecimal 类就是不变对象的示例 ― 它们表示在对象 的生命期内无法更改的单个值。

不变性的长处

如果正确使用不变类,它们会极大地简化编程。因为它们只能处于一种状态 ,所以只要正确构造了它们,就决不会陷入不一致的状态。您不必复制或克隆不 变对象,就能自由地共享和高速缓存对它们的引用;您可以高速缓存它们的字段 或其方法的结果,而不用担心值会不会变成失效的或与对象的其它状态不一致。 不变类通常产生最好的映射键。而且,它们本来就是线程安全的,所以不必在线 程间同步对它们的访问。

自由高速缓存

因为不变对象的值没有更改的危险,所以可以自由地高速缓存对它们的引用 ,而且可以肯定以后的引用仍将引用同一个值。同样地,因为它们的特性无法更 改,所以您可以高速缓存它们的字段和其方法的结果。

如果对象是可变的,就必须在存储对其的引用时引起注意。请考虑清单 1 中 的代码,其中排列了两个由调度程序执行的任务。目的是:现在启动第一个任务 ,而在某一天启动第二个任务。

清单 1. 可变的 Date 对象的潜在问题

Date d = new Date();   Scheduler.scheduleTask(task1, d);   d.setTime(d.getTime() + ONE_DAY);   scheduler.scheduleTask(task2, d);

因为 Date 是可变的,所以 scheduleTask 方法必须小心地用防范措施将日 期参数复制(可能通过 clone() )到它的内部数据结构中。不然, task1 和 task2 可能都在明天执行,这可不是所期望的。更糟的是,任务调度程序所用的 内部数据结构会变成讹误。在编写象 scheduleTask() 这样的方法时,极其容易 忘记用防范措施复制日期参数。如果忘记这样做,您就制造了一个难以捕捉的错 误,这个错误不会马上显现出来,而且当它暴露时人们要花较长的时间才会捕捉 到。不变的 Date 类不可能发生这类错误。

固有的线程安全

大多数的线程安全问题发生在当多个线程正在试图并发地修改一个对象的状 态(写-写冲突)时,或当一个线程正试图访问一个对象的状态,而另一个线程 正在修改它(读-写冲突)时。要防止这样的冲突,必须同步对共享对象的访问 ,以便在对象处于不一致状态时其它线程不能访问它们。正确地做到这一点会很 难,需要大量文档来确保正确地扩展程序,还可能对性能产生不利后果。只要正 确构造了不变对象(这意味着不让对象引用从构造函数中转义),就使它们免除 了同步访问的要求,因为无法更改它们的状态,从而就不可能存在写-写冲突或 读-写冲突。

不用同步就能自由地在线程间共享对不变对象的引用,可以极大地简化编写 并发程序的过程,并减少程序可能存在的潜在并发错误的数量。

在恶意运行的代码面前是安全的

把对象当作参数的方法不应变更那些对象的状态,除非文档明确说明可以这 样做,或者实际上这些方法具有该对象的所有权。当我们将一个对象传递给普通 方法时,通常不希望对象返回时已被更改。但是,使用可变对象时,完全会是这 样的。如果将 java.awt.Point 传递给诸如 Component.setLocation() 的方法 ,根本不会阻止 setLocation 修改我们传入的 Point 的位置,也不会阻止 setLocation 存储对该点的引用并稍后在另一个方法中更改它。(当然, Component 不这样做,因为它不鲁莽,但是并不是所有类都那么客气。)现在, Point 的状态已在我们不知道的情况下更改了,其结果具有潜在危险 ― 当点实 际上在另一个位置时,我们仍认为它在原来的位置。然而,如果 Point 是不变 的,那么这种恶意的代码就不能以如此令人混乱而危险的方法修改我们的程序状 态了。

Java理论

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号