第八条——覆盖equals方法时需遵守的通用约定
1)自反性
对于任何非null的引用值x,x.equals(x)必须返回true。---这一点基本上不会有啥问题
2)对称性
对于任何非null的引用值x和y,当且仅当x.equals(y)为true时,y.equals(x)也为true。
JDK中就有这样的错误。如java.sql.Timestamp对java.util.Date进行了扩展,并且增加了nanoseconds域。Timestamp的equals方法就违反了对称性。
下面我们来分析下这个方法
//Date.java
public boolean equals(Object obj) {
return obj instanceof Date && getTime() == ((Date) obj).getTime();
} //Timestamp.java
public boolean equals(java.lang.Object ts) {
if (ts instanceof Timestamp) {
return this.equals((Timestamp)ts);
} else {
return false;
}
} public boolean equals(Timestamp ts) {
if (super.equals(ts)) {
if (nanos == ts.nanos) {
return true;
} else {
return false;
}
} else {
return false;
}
}
比如说Date d ; Timestamp t.那么d.equals(t)==true,但是从Timestamp的equals方法可以看到,t.equals(d)==false
3)传递性
对于任何非null的引用值x、y、z。如果x.equals(y)==true,y.equals(z)==true,那么x.equals(z)==true。
这一条主要是针对子类增加了新的属性导致的.
我们可以再一个抽象的类的子类中增加新的属性,而不会违反equals约定。只要不能直接创建超类的实例,上述几种约定的问题就不会出现。
4) 一致性
对于任何非null的引用值x和y,只要equals的比较操作在对象所用的信息没有被修改,那么多次调用x.eqals(y)就会一致性地返回true,或者一致性的返回false。
5)非空性
所有比较的对象都不能为空。
许多类的equals方法都通过一个显示的null测试来防止这种现象,如下所示:
@override
public boolean equals(Object o) {
if(o==null) {
return false;
}
.........
}
其实没有必要,因为为了测试equals参数的等同性,equals方法必须先把参数转换成适当的类型,以便可以调用它的访问方法,或者域。在进行转换前,equals方法必须使用instanceof操作符,检查其参数是否为正确的类型,如下所示:
@override
public boolean equals(Object o) {
if(!(o instanceof MyType)) {//如果o==null,这一步就返回false
return false;
}
.........
}
综上所述,得出 以下实现高质量equals方法的诀窍
1. 使用==操作符检查“参数是否为这个对象的引用”。。这只不过是一种性能优化,如果比较操作可能跟昂贵,就值得这么做。
2. 使用instanceof操作符检查“参数是否为正确的类型”
3. 把参数转换成正确的类型
4. 对于该类的每个“关键”域,检查参数中的域是否与该对象中对应的域匹配。
注意域的比较顺序可能会影响equals方法的性能,为了获得最佳的性能,应该最先比较最不可能一致的域或者开销最小的域。
5. 当完成equals方法时,一定要检查是否符合:对称性、传递性、一致性
6. 覆盖equals方式时总是要覆盖hashCode方法
7. 不要企图让equals方法过于智能
8.不要把equals方法声明中的参数Object类型替换为其他类型(用@override标签保证此点)
第八条——覆盖equals方法时需遵守的通用约定的更多相关文章
- 重载equals方法时要遵守的通用约定--自反性,对称性,传递性,一致性,非空性
本文涉及到的概念 1.为什么重载equals方法时,要遵守通用约定 2.重载equals方法时,要遵守哪些通用约定 为什么重载equals方法时,要遵守通用约定 Object类的非final方法都 ...
- 覆盖equals方法时请遵守通用约定
覆盖equals方法时请遵守通用约定 覆盖equals方法看起来很简单,但是有许多覆盖方式会导致错误,并且后果很严重.最容易避免这种类问题的方法就是不覆盖equals方法,在这种情况下,类的每个实 ...
- 第九条:覆盖equals方法时总要覆盖hashCode方法
Object类的hashCode方法: public native int hashCode(); 是一个本地方法. 其中这个方法的主要注释如下: Whenever it is invoked o ...
- 【Java实战】源码解析为什么覆盖equals方法时总要覆盖hashCode方法
1.背景知识 本文代码基于jdk1.8分析,<Java编程思想>中有如下描述: 另外再看下Object.java对hashCode()方法的说明: /** * Returns a hash ...
- Effective Java 第三版——10. 重写equals方法时遵守通用约定
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- [改善Java代码]覆写equals方法时不要识别不出自己
建议45: 覆写equals方法时不要识别不出自己 我们在写一个JavaBean时,经常会覆写equals方法,其目的是根据业务规则判断两个对象是否相等,比如我们写一个Person类,然后根据姓名判断 ...
- Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- 使用equals方法时,要注意
这是我在项目中犯的一个低级错误: 使用equals方法时,要注意这个方法是boolean java.lang.String.equals(Object anObject)传递的是Object,所以传任 ...
- 为什么重写equals方法时,要求必须重写hashCode方法?
1 equals方法 Object类中默认的实现方式是 : return this == obj .那就是说,只有this 和 obj引用同一个对象,才会返回true. 而我们往往需要用equ ...
随机推荐
- 4542: [Hnoi2016]大数
Description 小 B 有一个很大的数 S,长度达到了 N 位:这个数可以看成是一个串,它可能有前导 0,例如00009312345.小B还有一个素数P.现在,小 B 提出了 M 个询问,每个 ...
- 我的前端之旅--SeaJs基础和spm编译工具运用[图文]
标签:seajs nodejs npm spm js 1. 概述 本文章来源于本人在项目的实际应用中写下的记录.因初期在安装和使用Seajs和SPM的时候,有点不知所措的经历.为此,我 ...
- BZOJ 3563 DZY Loves Chinese
Description 神校XJ之学霸兮,Dzy皇考曰JC. 摄提贞于孟陬兮,惟庚寅Dzy以降. 纷Dzy既有此内美兮,又重之以修能. 遂降临于OI界,欲以神力而凌♂辱众生. 今Dzy有一魞歄图,其上 ...
- [BZOJ 1028] [JSOI2007] 麻将 【枚举+贪心判断】
题目链接:BZOJ - 1028 题目分析 枚举听的是哪种牌,再枚举成对的是哪种牌,再贪心判断: 从1到n枚举每一种牌,如果这种牌的个数小于0,就返回不合法. 将这种牌的张数 % 3, 剩下的只能和 ...
- The type java.lang.String cannot be resolved. It is indirectly referenced from required .class files
最近在做J2ME开发项目,配置环境一切OK,但是打开项目时某些文件提示: The type java.lang.String cannot be resolved. It is indirectly ...
- zoj 3841 Cards
题意:给你52张牌,已知一个牌的序列,然后利用剩余的牌,能排成多少个序列,这个序列比已知的序列字典序小. 思路:从左到右尽可能放比已知序列相应位置小,找不到就放一样,然后求组合数就可以.多重集排列定理 ...
- php的ob实现页面静态化
php页面静态化的原理,用最少的代码解释页面静态化 如何应用:在插入或更新数据到数据库时,就执行一下代码是一种比较好的方法.比如:php执行add()方法时(就是插入数据时) //开启缓存 Ob_st ...
- [SQL Server]一次执行资料夹内的.sql 指令码
原文:[SQL Server]一次执行资料夹内的.sql 指令码 初始资料库时,我们Developers们会准备很多.sql指令码来建立资料表.检视甚至初始资料,那麽要怎麽一次执行资料夹内的*.sql ...
- mysql 服务意外停止1067错误解决办法小结
今天在配置服务器时安装mysql5.5总是无法安装,查看日志错误提示为1067错误,下面来看我的解决办法 事件类型: 错误 事件来源: Service Control Manager 事件种类: 无 ...
- lc面试准备:Implement Stack using Queues
1 题目 Implement the following operations of a stack using queues. push(x) -- Push element x onto stac ...