第八条:覆盖equals时请遵守通用约定

什么时候需要覆盖equals方法?类具有自己的逻辑相等概念,并且父类的equals方法不能满足需要。
重写equals时需要遵循一下约定:

  • 自反性:非null x,x.equals(x)必须是true
  • 对称性:非null x和y,y.equals(x)和x.equals(y)的结果必须一致
  • 传递性:非null x、y、z,如果x.equals(y)和x.equals(z)的结果为true,那么y.equals(z)也必须为true
  • 一致性:非null x、y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)的结果就一致。
  • 对于非null x,x.equals(null)一定是false

自反性:不知道怎么写能让这个返回false,如果返回false了,那么把结果添加到Collection集合类中时,那么contains方法就会一直返回false
对称性:

class Fifth1 {
private String s; public Fifth1(String s) {
this.s = s;
} @Override
public boolean equals(Object o) {
if (o instanceof Fifth1) {
return s.equalsIgnoreCase(((Fifth1) o).s);
}
if (o instanceof String) {
return s.equalsIgnoreCase((String) o);
}
return false;
}
}
    Fifth1 fifth1 = new Fifth1("FZK");
String s = "fzk";

这两个比较就违反了自反性,fifth1.equals(s)调用自定义的equals方法,s.equals(fifth1)调用String的equals方法。

    List<Fifth1> list = new ArrayList<Fifth1>();
list.add(fifth1);
list.contains(s);

然后又有这种代码,结果可能是true,也可能抛运行时异常。
传递性:

class Point {
private final int x;
private final int y; public Point(int x, int y) {
this.x = x;
this.y = y;
} @Override
public boolean equals(Object obj) {
if (!(obj instanceof Point))
return false;
Point p = (Point) obj;
return p.x == x && p.y == y;
}
} class ColorPoint extends Point {
private final String color; public ColorPoint(int x, int y, String color) {
super(x, y);
this.color = color;
} }

ColorPoint肯定需要一个equals。

  @Override
public boolean equals(Object obj) {
if (obj instanceof ColorPoint) {
return false;
}
return super.equals(obj) && ((ColorPoint)obj).color.equals(color);
}
    Point p = new Point(1, 1);
ColorPoint colorPoint = new ColorPoint(1, 1, "red");

这两个比较会失去对称性。
这么写equals:

  @Override
public boolean equals(Object obj) {
if (obj instanceof ColorPoint) {
return false;
}
if (!(obj instanceof ColorPoint)) {
return obj.equals(this);
}
// obj is a ColorPoint
return super.equals(obj) && ((ColorPoint)obj).color.equals(color);
}

Point p = new Point(1, 1);
ColorPoint colorPoint1 = new ColorPoint(1, 1, "red");
ColorPoint colorPoint2 = new ColorPoint(1, 1, "blue");
colorPoint1.equals(p);
colorPoint2.equals(p);
colorPoint1.equals(colorPoint2);

比较这三个的时候又会失去传递性。
其实上面的那种设计,没有什么特别好的办法。改变设计框架还能解决上面的问题,第一中办法是将Color作为ColorPoint的成员。另一种办法是将超类建成抽象类,只要不能直接实例花超类的实例,上面的问题就不会发生。

一致性:相等的永远相等,除非改变了什么。在比较的时候,不要使equals依赖不可靠的资源。

非空性:书的作者起的名,指所有的对象和null 比较的时候都不能返回true。还有在方法里不能返回NullpointerException。
在写完一个equals方法时一定要考虑是否是对称的,传递的,一致的。自反和非空通常会自动满足。

忠告:

  • 覆盖equals时也要覆盖hashCode()方法。
  • 不要企图让equals过于智能,会出现很多麻烦的东西
  • 不要将生命的Object替换成其他的东西。如果是其他的就是重载而不是覆盖。

第九条:覆盖equals时总要覆盖hashCode方法

如果覆盖了equals而没有覆盖hashCode,会违反Object.hashCode的通用约定,导致该类无法结合所有基于散列的集合一起正常运作,这样的集合包括HashMap,HashSet,HashTable。

Object规范:

  • 在应用的执行期间,只要对象的equals方法的比较所用到的信息没有被修改,那么对这个同一对象调用多次,hashCode方法都返回同一个正数。在同一个应用程序的多次执行过程中,每次执行所返回的正数可以不一致
  • 如果两个对象根据equals比较相等,那么hashCode放回的整数一定相等
  • 如果两个对象根据equals比较不相等,那么hashCode放回的整数有可能相等。但是应该知道,不同对象返回hashCode不相等会提高散列表的性能。

第十条:始终要覆盖toString方法

第十一条:谨慎地覆盖clone

地十二条:考虑实现Comparable

书中太啰嗦,感觉没什么好说的。

Effective java -- 2 对于所有对象都通用到方法的更多相关文章

  1. Effective Java:对于全部对象都通用的方法

    前言: 读这本书第1条规则的时候就感觉到这是一本非常好的书.可以把我们的Java功底提升一个档次,我还是比較推荐的.这里我主要就关于覆盖equals.hashCode和toString方法来做一个笔记 ...

  2. 《Effective Java》—— 对于所有对象都通用的方法

    本节主要涉及Object中通用的一些方法,比如equals,hashCode,toString,clone,finalize等等 覆盖equals时请遵守通用约定 equals方法实现的等价关系: 自 ...

  3. [Effective Java]第三章 对所有对象都通用的方法

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  4. [Effective Java 读书笔记] 第三章 对所有对象都通用的方法 第八 ---- 九条

    这一章主要讲解Object类中的方法, Object类是所有类的父类,所以它的方法也称得上是所有对象都通用的方法 第八条 覆盖equals时需要遵守的约定 Object中的equals实现,就是直接对 ...

  5. Java高效编程之二【对所有对象都通用的方法】

    对于所有对象都通用的方法,即Object类的所有非final方法(equals.hashCode.toString.clone和finalize)都有明确的通用约定,都是为了要被改写(override ...

  6. 《Effective Java》第3章 对于所有对象都通用的方法

    第8条:覆盖equals时请遵守通用约定 覆盖equals方法看起来似乎很简单,但是有许多覆盖方式会导致错误,并且后果非常严重.最容易避免这类问题的办法就是不覆盖equals方法,在这种情况下,类的每 ...

  7. Effective Java读书笔记——第三章 对于全部对象都通用的方法

    第8条:覆盖equals时请遵守通用的约定 设计Object类的目的就是用来覆盖的,它全部的非final方法都是用来被覆盖的(equals.hashcode.clone.finalize)都有通用约定 ...

  8. [Java读书笔记] Effective Java(Third Edition) 第 3 章 对于所有对象都通用的方法

    第 10 条:覆盖equals时请遵守通用约定 在不覆盖equals方法下,类的每个实例都只与它自身相等. 类的每个实例本质上都是唯一的. 类不需要提供一个”逻辑相等(logical equality ...

  9. 《Effective Java》第2章 对所有对象都通用的方法

    第10条:覆盖equals时,请遵守通用约定 1.使用==来比较两个对象的时候,比较的是两个对象在内存中的地址是否相同(两个引用指向的是否为同一个对象):Object中定义的equals方法也是这样比 ...

随机推荐

  1. 一个有意思的 hta 程序 (html application)

    哈哈,刚才同事给我讲了一个hta 程序,他自己说最近在学html5 开发坦克大战,不错,这种好奇心, 好学的精神值得我这个程序员学习,感觉他的视野面比我这个程序员还广,有点小惭愧. 什么是hta 呢? ...

  2. angularJS在创建指令需要注意的问题(指令中使用ngRepeat)

    现在发现,当初的自己真的是太菜了,为什么你在指令中更改数据,没有作用呢?这其实是原型链的问题. 详细的我就不在这里说了,有位大神早已发布了这个内容,在这里复制个地址给大家,有兴趣的可以看看 http: ...

  3. openwrt系统之字符设备驱动软件包加载、测试程序加载

    .首先将软件包(如mydrv)放到ubuntu虚拟机openwrt/trunk/package/kernel/目录下 .回到openwrt/trunk/目录下,make menuconfig进行配置, ...

  4. java多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么?

    多线程有两种实现方法,分别是继承Thread类与实现Runnable接口 同步的实现方面有两种,分别是synchronized,wait与notify 先看一下java线程运行时各个阶段的运行状态 j ...

  5. google-c-style

    http://zhanxw.com/blog/2011/03/learning-and-applying-coding-style-from-google-in-emacs/ http://stack ...

  6. read gc log

    http://www.aichengxu.com/article/Java/18368_2.html https://blogs.oracle.com/poonam/entry/understandi ...

  7. The 2014 ACMICPC Asia Regional Guangzhou Online

    [A]-_-/// [B]线段树+位运算(感觉可出) [C]地图BFS,找最长线 [D]地图BFS,加上各种复杂情况的最短路-_- [E]-_-/// [F]三分+圆与线段的交点,计算几何 [G]-_ ...

  8. MYSQL同步--主从同步问题集锦

    1  同步停止,报错误:  Could not find first log file name in binary log index file 数据库主从出错: Slave_IO_Running: ...

  9. keystone policy.json 的学习总结

    keystone的policy.json文件位于:/etc/keystone/policy.json 其内容如下: 1 { 2 "admin_required": "ro ...

  10. POJ 1696 Space Ant

    极角排序 每次选择一个最外围的没选过的点,选择的时候需要利用极角排序进行选择 #include<cstdio> #include<cstring> #include<ve ...