一. 什么情况下需要覆盖equals方法
1.类的每个实例本质上是唯一的equals,对于代表活动的实体,而非值的类. 在我的理解中,Spring开发过程中Service,DAO等就可以不覆盖equals方法,而那些bean则是必须覆盖的.
2.不关心类是否提供了"逻辑想等(logical equality)"的测试功能,不需要提供覆盖,例如Java的java.util.Random
3. 父类已经覆盖了equals,从父类继承过来的行为对于子类也是合适的,这时不需要覆盖,(原文使用超类,但我认为父类比较符合我的日常认知)
4. 类是私有地或者包级私有地,可以确定它的equals方法永远不被调用,这时需要覆盖,防止被调用
5. 当类有自己特有的"逻辑想等"概念,而且父类还没有覆盖equals以实现期望的行为
二. equals的通用约定
1. 自反性(reflexive).对于任何非null的引用值x,x.equals(x)必须返回true
2. 对称性(symmetric).对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,必须有x.equals(y)返回true
3.传递性(transitive).对于任何非null的引用值x,y,z,如果x.equals(y)返回true且y.equals(z)返回true,则必须有z.equals(x)返回true
4.一致性(consistent).对于任何非null的 引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)会一致返回true或者false
5. 对于任何非null的引用值x,x.equals(null)必须返回false
三. 实现高质量equals诀窍
1. 使用==操作符检查"参数是否为这个对象的引用",如果是返回true,能够达成一种性能的优化
2. 使用instanceof操作符检查"参数是否为正确的类型"如果不是返回false.
3. 把参数转成正确的类型,因为转换之前进行过instanceof测试,所以转换会成功
4. 对于类中每个"关键significant"域,检查参数中的域是否与该对象中对应的域匹配
5.完成编写后,询问自己三个问题,是否对称,是否能够传递,是否一致
四. 一些告诫
1. 覆盖equals时总要覆盖hashCode
2.不要企图让equals方法过于智能
3.不要将equals声明中的Object对象替换为其他的类型
五. 最后
使用ide开发的同学可以使用ide的快捷键生产equals与hashcode代码,idea的是alt+insert. eclipse的右键->source