文档章节

第三章:对于所有对象都通用的方法。ITEM8:覆盖equals时请遵守通用约定。

t
 twoslow
发布于 2014/09/04 15:04
字数 1110
阅读 2
收藏 0

1、什么时候需要覆盖equals?如果类具有自己特有的“逻辑相等”概念,而且超类还没有覆盖equals。

2、覆盖equals时需要遵守的约定:

  • 自反性。对于任何非null的引用值x,x.equals(x)必须返回true。
  • 对称性。对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。
 1 package com.twoslow.cha3;
 2 
 3 /**
 4  * 对称性
 5  */
 6 public class CaseInsensitiveString {
 7 
 8     private final String s ;
 9     
10     public CaseInsensitiveString(String s) {
11         if(s == null)
12             throw new NullPointerException() ; 
13         this.s = s ; 
14     }
15     
16     @Override
17     public boolean equals(Object o) {
18         /*
19          * String类中的方法并不知道CaseInsensitiveString类型的字符串,总是返回false,违反了对称性
20          * if(o instanceof CaseInsensitiveString)
21                 return s.equalsIgnoreCase(((CaseInsensitiveString)o).s) ;
22             if(o instanceof String)
23                 return s.equalsIgnoreCase(((String)o)) ;
24         */
25         /**
26          * 把与String互操作的代码去掉
27          */
28         return (o instanceof CaseInsensitiveString) && ((CaseInsensitiveString)o).s.equalsIgnoreCase(s) ;
29     }
30     
31 }

 

  • 传递性。对于任何非null的引用值x、y、z,如果x.equals(y)返回true,并且y.equals(z)返回true,则x.equals(z)必须返回true。
 1 package com.twoslow.cha3;
 2 
 3 import java.awt.Color;
 4 
 5 public class ColorPoint extends Point{
 6 
 7     private final Color color ; 
 8     
 9     public ColorPoint(int x, int y,Color color) {
10         super(x,y) ;
11         this.color = color ; 
12     }
13     
14     /**
15      * 在比较普通点和有色点,或者相反的情况时,前一种忽略了颜色
16      * 后一种总是返回false
17      */
18     @Override
19     public boolean equals(Object o) {
20         if(!(o instanceof ColorPoint))
21             return false ;
22         return super.equals(o) && ((ColorPoint)o).color == color ;
23     }
24 
25 }
26 
27 
28 package com.twoslow.cha3;
29 
30 import java.awt.Color;
31 
32 /**
33  * 复合优先于继承
34  */
35 public class ColorPoint02{
36 
37     private final Point point ;
38     private final Color color ; 
39     
40     public ColorPoint02(int x, int y,Color color) {
41         if(color == null)
42             throw new NullPointerException() ;
43         point = new Point(x,y) ;
44         this.color = color ; 
45     }
46     //提供一个视图方法返回内部的 Point 对象实例。这里 Point 实例为 final 对象非常重要,
47     //可以避免使用者的误改动。视图方法在 Java 的集合框架中有着大量的应用。
48     public Point asPoint() {
49         return point ;
50     }
51     
52     @Override
53     public boolean equals(Object o) {
54         if(!(o instanceof ColorPoint02))
55             return false ;
56         ColorPoint02 other = (ColorPoint02) o ;
57         return other.point.equals(point) && other.color.equals(color) ;
58     }
59 }

 

  • 一致性。对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致地返回true,或者一致返回false。
  • 对于任何非null的引用值x,x.equals(null)必须返回false。
 1 @Override public boolean equals(Object o) {
 2         if (o == null)
 3             return false;
 4         if (!(o instanceof MyType))
 5             return false;
 6         }
 7 
 8 //    注意以上代码中的 instanceof 判断,由于在后面的实现中需要将参数 o 进行类型强转,如果类型不
 9 //    匹配则会抛出 ClassCastException,导致 equals 方法提前退出。在此需要指出的是 instanceof 还有一
10 //    个潜在的规则,如果其左值为 null,instanceof 操作符将始终返回 false,因此上面的代码可以优化为:
11     @Override public boolean equals(Object o) {
12     if (!(o instanceof MyType))
13         return false;
14     }

 

   鉴于之上所述,该条目中给出了重载 equals 方法的最佳逻辑:
1.使用==操作符检查"参数是否为这个对象的引用",如果是则返回 true。由于==操作符是基于对象地址的比较,因此特别针对拥有复杂比较逻辑的对象而言,这是一种性能优化的方式。
2.使用 instanceof 操作符检查"参数是否为正确的类型",如果不是则返回 false。
3.把参数转换成为正确的类型。由于已经通过 instanceof 的测试,因此不会抛出ClassCastException 异常。
4.对于该类中的每个"关键"域字段,检查参数中的域是否与该对象中对应的域相匹配。

5.如果域字段为 Object 对象,则使用 equals 方法进行两者之间的相等性比较,如果为 int 等整型基本类型,可以直接比较,如果为浮点型基本类型,考虑到精度和 Double.NaN
   和 Float.NaN 等问题,推荐使用其对应包装类的 compare 方法,如果是数组,可以使用 JDK 1.5 中新增的 Arrays.equals 方法。众所周知,&&操作符是有短路原则的,因此应该将最有可能不相同和比较开
   销更低的域比较放在最前面。

© 著作权归作者所有

t
粉丝 0
博文 15
码字总数 6644
作品 0
南开
私信 提问
《Effective Java》学习笔记 第三章 对于所有对象都通用的方法

1 覆盖equals时请遵守通用约定 覆盖方法看起来似乎很简单,但是许多覆盖方式会导致错误,并且后果非常严重,最容易避免该问题的办法就是不覆盖方法,这种情况下,类的每个实例都只与它自身相...

newtrek
05/28
0
0
《Effective Java》读书笔记

Effective Java读书笔记 第一章:引言 第二章:创建和销毁对象 第一条:创建对象的方式 1、构造器 2、 静态方法 3、构建器 第三条::强化singleton 1、三种方式实现单例 枚举实现(最佳方式)...

磊神Ray
2011/09/06
195
0
覆盖equals时请遵守通用约定(8)

1、覆盖equals方法需谨慎,可能会导致严重后果 最容易避免的方式就是,不去覆盖 2、覆盖equals 方法期望你满足: (1)类的每个实例本质上都是唯一的 代表活动实体而不是值得类确实如此 Obje...

职业搬砖20年
2018/05/24
14
0
《Effective Java 第三版》目录汇总

经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习。时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正。 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用...

M104
04/04
0
0
Effective Java 第三版——10. 重写equals方法时遵守通用约定

Tips 《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8...

M104
2017/12/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

python学习10.04:Python list列表使用技巧及注意事项

前面章节介绍了很多关于 list 列表的操作函数,细心的读者可能会发现,有很多操作函数的功能非常相似。例如,增加元素功能的函数有 append() 和 extend(),删除元素功能的有 clear()、 remo...

太空堡垒185
11分钟前
2
0
新手插画学习的方法?教你如何自学?

插画学习的方法?教你如何自学? 从小喜欢画一些漫画头像随笔画,但是其实没有基础。个人偏好小清新手绘风的插画(如下图),每每看到都希望自己能画出这样的作品。 我其实很想说画这种美术功...

huihuajiaocheng
16分钟前
3
0
面试题

1、实现clone();

gtandsn
27分钟前
3
0
CentOS 7 部署 tesseract-ocr

官方地址 github yum-config-manager --add-repo https://download.opensuse.org/repositories/home:/Alexander_Pozdnyakov/CentOS_7/ 若提示 yum-config-manager: command not found 执行以......

阿白
27分钟前
2
0
JAVA比较器中comparator的使用

一个专用的比较器Comparator Comparator是一个专用的比较器,当一个不支持自比较或者自比较函数不能满足要求时,可写一个比较器来完成两个对象之间大小的比较。Comparator体现了一种策略模式...

daxiongdi
28分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部