跟我学(Effective Java 2)第8条:覆盖equals时请遵守通用约定

本文深入探讨了在Java中覆盖equals方法时应遵循的通用约定及注意事项,强调了自反性、对称性、传递性和一致性的重要性。文章还提到了在覆盖equals方法时通常需要同时覆盖hashCode方法,以及避免常见陷阱的建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

覆盖equals方法看起来似乎很简单,但是有很多覆盖方式会导致错误,并且后果非常的严重。最容易避免这类问题的办法就是补覆盖equals方法,在这种情况下,类的每个实例都只是与它自身相等。如果满足以下任何一个条件,这正是所期望的结果:

1 类的每个实例本质上都是唯一的。对于代表活动实体而不是值(value)的类来说,例如Thread。Object提供的equals实现对于这些类来说正是正确的行为。

2 不关心类是否提供了“逻辑相等(logical equality)”的测试功能。例如,java.util.Random覆盖了equals,以检查两个Random实例是否产生相同的随机数列,但是设计者并不认为客户需要或者期望这样的功能。在这样的情况下,从Object继承的equals实现就已经足够了。

3 超类已经覆盖了equals,从超类继承过来的行为对于子类也是合适的。例如,大多数的Set实现都从AbstractSet继承equals实现,List实现从equals实现,Map实现从AbstractMap继承equals实现。

4 类是私有的或者包级私有的,可以确定它的equals方法永远不会被调用。在这种情况下,无疑是应该覆盖equals的,以防止它被意外调用。

在覆盖equals方法的时候,你必须要遵守它的通用约定。
equals方法实现了等价关系(equivalence relation):

自反性(reflexive):对于任何非null的引用值x,x.equals(x)必须返回true。
对称性(symmetric):对于任何非null的引用值x与y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。
传递性(transitive):对于任何非null的引用值x、y和z,如果x.equals(y)返回为true,并且y.equals(z)也返回true,那么x.equals(z)也必须返回true。
一致性(consistent):对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致地返回true,或者一致地返回false。
对于任何非null的引用值x,x.equals(null)。

 //此方式是防止被意外调用
    @Override
    public boolean equals(Object obj) {

        throw new AssertionError();
        //return super.equals(obj);
    }
    //从写equals方式5大原则
    /*
    1, 自反性 z.equals(z) == true
    2,对称性 z.equals(y) == true 则  y.equals(z) == true
    3,一致性  z.equals(y) == true 如果两者不进行修改 则一直为true
    4,传递性  z.equals(y) == true  y.equals(x) == true 则  z.equals(x) == true
    5,非空性  z.equals(null) == false

    方式:
        1)使用 == 来检查 是否是这个对象的引用
        2)使用 instanceof 来检查 是否是正确的类型
        3)转换参数为正确的类型
        4)对于该类中的 关键域(成员变量为对象) 检查参数中的域是否与该对象中应对的域相匹配
        经典用法Objects内((a == b) || (a != null && a.equals(b)))
        5)保持 对称性 传递性 一致性

    注: 覆盖equals方法时 一般都覆盖hashCode方法
        不要将equals声明中的boj对象改为其他类型,那样并不是覆盖而是重载,应该用@Override避免发生
     */
里氏替换原则 (Liskov substitution principle):各个类型的任何重要属性也将适用于它的子类型。因此在为该类型编写怕任何方法,在它的子类型上也应该同样运行得很好。

**当编写完成equals方法之后,应该考虑它是否是对称的,传递的,一致的。**还要编写些测试用例用来测试。一般情况下,自反和非空会自动满足。
一些关于写equals的告诫:

1、覆盖equals时总是要覆盖hashCode。

2、不要企图让equals方法过于智能。过度去寻找各种等价关系很容易陷入麻烦之中。

3、不要将equals声名中的Object对象替换成其他的类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值