`
逆天子军少
  • 浏览: 77709 次
  • 性别: Icon_minigender_1
  • 来自: 安庆
社区版块
存档分类
最新评论

对于所有对象都通用的方法

阅读更多
尽管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.使用==操作符检查“参数是否为这个对象的引用”。
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、正整数。如果没法进行比较,抛出异常。


2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics