|
![]() |
名片设计 CorelDRAW Illustrator AuotoCAD Painter 其他软件 Photoshop Fireworks Flash |
|
这是第2篇 二。对于所有对象都通用的方式 主要介绍如何准确地改写Object类中的非final方式。 第7条:在改写equals的时候请遵守通用的约定 改写equals方式所必须遵守的几个约定 1。自反性:X.equals(X)必须返回true 2。对称性:Y.equals(X)返回的必须和X.equals(Y)一致 3。传递性:X.equals(Y),Y.equals(Z)假如返回true的话,那么X.equals(Z)也必须返回true 4。一致性:多次调用X.equals(Y)返回的值应该是一致的 5。非空性:X.equals(null)必须返回false 这里最轻易产生错误的是第2和第3条。要保证第2条你必须保证不扩大比较的对象的范围。而第3条产生的问题一般在继续的过程中,子类扩展了父类,增加了新的变量,涉及到面向对象关系理论的一个基本问题,那就是: 要想在扩展一个可实例化的类的同时,既要增加新的特征,同时还要保留equals约定,没有一个简朴的方式可以做到这一点。 撰写高质量的equals方式的一些处方或者说告戒: a.使用"=="检查引用是否为空 b.使用instanceOf检查对象的类别是否准确 c.把实参转变到准确的类型,并保证明际参数中的"要害域"与当前对象中对应的域是否匹配 d.编写完equals之后应该检查是否满意:对称性,传递性,一致性 e.当你改写equals的时候,总要改写hashCode f.不要企图让equals方式过于智慧,加入太多等价关系比较只会让事情变糟糕 g.不要使equals方式依靠于不可靠的资源 h.不要使equals声明中的Object对象替换为详细的类型对象 不过,你可以用组合代替继续,在新的类中加入一个原有类的对象,而不是继续它,这样就不会碰到保持equals的问题了。 第8条:在改写equals时总是要改写hashCode 假如不这样做的话,就导致该类无法与所有基于散列值的集合类型一起正常工作,如HashSet,HashMap。一个理想的散列函数应该把一个集合中的不相等的对象均匀的分布到所有可能的散列值上,书中提供了一种方式接近理想状态 1.把某个非0的常整数保存在一个叫result的int型变量中 2。对于对象中的每一个要害域f完成下列步骤 a。为该域计算散列码c: i.假如是boolean f?0:1 ii.byte,char,shor,int型 (int)f iii.long型 (int)(f^(f>>32)) ivfloat型 Float.floattoIntBits(f) v.double型 Double.doubletoLongBits(f)得到一个long型,然后按iii计算 vi.假如是一个对象引用可以递归调用hashCode()或者计算一个另外的“规范表示” vii。假如是一个数组,则把每一个元素当作一个单独的域来处理 b.按公式计算散列码 result=37*result+c; 3。返回result 还一点,一定要包括该类的要害性的变量,不要试图通过排除一个对象的要害部分来获得性能的提高 第9条:总是改写toString() 这一条更多的是为了提供更有价值的信息给使用者,我很少使用这点,惭愧 第10条:谨慎地改写clone() 实现对象的深层拷贝。可以这样认为,clone()方式是另一个构造函数!要编写一个行为准确的clone()方式,特殊是对于一些类的内部具有可变的域是相称困难的。首先你必须实现cloneable接口,在clone()方式中调用super.clone(),然后修改任何需要修改的变量。例如,要对上一骗文章的Stack撰写一个准确的clone方式如下 public Object clone() throws CloneNotSupportedException{ Stack result=(Stack)super.clone(); result.elements=(Object)elements.clone(); return result; } 前提要求elements不是final. clone()方式的改写是复杂的,甚至是危险的,还有另一种方式来提供拷贝对象的功能,那就是拷贝构造函数。这同样不是C++专有的概念。 例如public Example(Example),你传入一个同类型的对象,然后在这个构造函数中做变量的拷贝就OK了。相比于Cloneable接口的复杂度,这是一个更好的解决办法。 第11条:考虑实现Compareable接口 此接口的实现类似于equals方式,也要保持对称,传递,一致等特性,详细不再介绍,假如你需要对某个类的对象实行排序等算法或者与Collections Framework中的类打交道,你该考虑实现这个接口 返回类别: 教程 上一教程: 虚拟机概论(四)??虚拟机的历史 下一教程: 用Groovy Template 生成代码 您可以阅读与"《Effective Java》学习笔记(2)"相关的教程: · 《Effective Java》学习笔记(1) · 《Effective Java》学习笔记(3) · 《Effective Java》学习笔记(4) · Java的“对象思想”学习笔记[二] · Java软件开发学习笔记(三) |
![]() ![]() |
快精灵印艺坊 版权所有 |
首页![]() ![]() ![]() ![]() ![]() ![]() ![]() |