尽管Object是一个具体类,但设计它主要是为了扩展。它所有的非final方法都有明确的通用规定。任何一个类,在覆盖这些方法的时候,都有
责任去遵守这些通用规定,如果不能做到这一点,其他依赖于这些规定的类就无法
结合该类一起正常
运作。
第八条:
覆盖equals时请遵守通用规定
如果类具有自己特有的逻辑相等概念(不同于对象等同的概念),而且超类还没有覆盖equals以实现期望的行为,这时就需要覆盖equals方法。在覆盖时,需要遵守下面的通用约定;
1.自反性 x.equals(x)必须返回true
2.对称性 y.equals(x)返回true时,x.equals(y)必须返回true
3.传递性 如果x.equals(y)返回true,y.equals(z)返回true, 那么x.equals(z)返回true
4.一致性 只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致返回true,或者一致返回false
5.对于非null的引用值x,x.equals(null)必须返回false。
下面是实现高质量equals方法的诀窍:
1.使用==
caozuofu.html" target="_blank">操作符检查“参数是否为这个对象的引用”。
2.使用
instanceof操作符检查“参数是否为正确的类型”。
3.把参数转换成正确的类型。
4.对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域相匹配。
5.当你编写完成了equals方法,应该检查是否是对称的、传递的、一致的。
6.不要企图让equals方法过于
智能
7.不要将equals声明中的Object对象替换成其他的类型
8.覆盖equals方法时总要覆盖
hashCode
第九条:覆盖equals时总要
覆盖hashCode
如果不覆盖hashCode,将导致该类无法结合所有基于散列的集合一起正常工作,比如:HashMap,HashSet,Hashtable
下面是约定的内容;
1.在应用程序执行期间,只要对象的equals方法的比较操作符所用的信息没有被修改,那么对同一个对象调用多次,hashCode方法都必须返回一个整数。在一个程序的多次执行过程中,可以不一致。
2.如果两个对象根据equals方法比较是相等的,那么调用这两个对象的任何一个hashCode方法都必须产生同样的整数结果
3.如果两个对象不相等,
他们的hashCode方法不一定产生不同的整数结果。但是,给不相等的对象产生不同的整数结果,有可能提高散列表的性能。
第十条:始终要
覆盖toString
虽然Object提供了toString的一个实现,但返回的字符串通常不是用户期望看到的。它包含类的名称,以及一个“@“,接着就是散列吗的无符号十六进制表示法。当对象被传递给println或者被调试器打印出来时,toString方法会被自动调用。提供好的toString方法,不仅有利于这个类的实例,同样也有益于包含这些实例的引用的对象。
在实现toString时,你可以决定是否在文档中指定返回值的格式。这样增强可读性,但一旦指定,就必须始终如一的坚持。所以无论是否指定格式,都应该在文档中明确的表明你的意图。
第十一条:
谨慎的
覆盖clone
Cloneable
接口的目的是作为对象的一个mixin接口,表明这样的对象允许克隆。但它缺少一个clone方法,Object的clone方法是受保护的。如果不借用反射,就不能达到调用clone方法的目的。既然Cloneable并没有包含任
何方法,那么它到底有什么作用呢?
如果一个类实现了Cloneable,那么Object的clone方法就返回该对象的逐域拷贝,否则就抛出
异常。因此,该类必须遵守一个复杂的,不可实施的
协议。由此得到一种语言之外的机制:无需调用
构造器就可
创建对象。
实际上,clone方法就是另一个构造器,但必须确保他不会伤害原始的对象,并确保正确的创建被克隆对象中的约束条件。
总之,所有实现了Cloneable接口的类都应该用一个公有的方法覆盖clone。该方法先调用super.clone,然后修正任何需要修正的域。一般情况下,这意味着要拷贝任何包含内部”深层结构“的可变对象,并用指向新对象的引用代替原来指向这些对象的引用。
第十二条:考虑
实现Comparable接口
compareTo方法并没有在Object中声明,相反,它是Comparable接口中唯一的方法。compareTo方法不但允许进行简单的等同性比较,而且允许执行顺序比较。类实现了Comparable接口就表明它的实例具有内在的排序关系。实现排序就这么简单:
Arrays.sort(a);
如果你正在编写一个值类,它具有非常明显的内在排序关系,比如按字母排序、按数值排序或者按年代排序,那你就应该坚决考虑实现这个接口。当该对象小于、等于、大于指定对象的时候,分别返回一个负整数、0、正整数。如果没法进行比较,抛出异常。