《Effective Java》第8条覆盖equals时请遵守通用约定

一. 什么情况下需要覆盖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

猜你喜欢

转载自blog.csdn.net/qq_34332035/article/details/81942278
今日推荐