关闭

关于重写equals();

标签: equalsjava
119人阅读 评论(0) 收藏 举报
      

今天复习了下 《Effective Java》的第八条,特地做下笔记。

包括:

一. 为什么要覆盖 equals

二. 覆盖 equals 的通用约定

三. 如何覆盖 equals (重点)



一. 为什么要覆盖 equals:

简单来说,就是为了要逻辑相等。两个对象,不管他们的内存地址,关心的只是他们的内容是否相等。

二. 覆盖 equals 的通用约定:

覆盖的时候不能瞎覆盖,不能随便写个 @override 就完事了,需要满足 自反性,对称性,传递性,一致性,以及对于任何非 null 的引用值 x,x.equals(null) 必须返回 false

怎么说呢,比如说

1. 自反性,a.equals(a) ;

2. 对称性,a.equals(b) 同时也要 b.equals(a) 。

3. 传递性,这个就是考虑到继承的情况,比如说像下面这样编译的时候


可以看到warning:总是想为我生成 equals 和 hasCode 方法。因为我继承了父类,那么这个类的 equals 方法是父类的,使用该类的 equals 将调用父类的 equals,所以说该类的这些成员变量都不会比较了。 例如:这里有一个 ClassA,重写 equals 方法:
public class ClassA {
    private int numA;
    public ClassA(int numA){
        this.numA = numA;
    }

    @Override
    public boolean equals(Object object) {
        if(object instanceof ClassA){
            if(numA == ((ClassA) object).getNumA()){
                return true;
            }
        }
        return false;
    }

    public int getNumA(){
        return numA;
    }
}

然后有 ClassB,继承了 ClassA,实际上ClassB用的就是ClassA的equals方法:

public class ClassB extends ClassA{
    public ClassB(int numA,int numB){
        super(numA);
        this.numB = numB;
    }
    private int numB;
}

那么,在使用的时候,如下:

public class Main {
public static void main(String args[]) {
        ClassB classB1 = new ClassB(1,2);
        ClassB classB2 = new ClassB(1,3);

        System.out.println(classB1.equals(classB2));
    }
}

就会输出 true 了。

那么,这点写的有点多,主要也是为了提醒,当我们写equals方法的时候,记得要 call super 的 equals 方法,然后再比较本类的 equals 方法。

像 lombok 就很贴心的提供了 @EqualsAndHashCode(callSuper=true) 注解。

4. 一致性,调多次都是返回这个。

5. 对于任何非 null 的引用值x, x.equals(null) 必须返回 false。

三. 如何覆盖 equals (重点):

如何 equals 方法还要自己来覆盖,那么就真 out 了。参考这里 JAVA如何快速重写int hashcode()? - 编程@用心阁 提到了几种方法,有 谷歌的,apache的,jdk的,以及IDE的。本人在工作中就是使用 lombok 的 @EqualsAndHashCode 注解。官方有其介绍 @EqualsAndHashCode

那么,如何非要自己实现,根据《Effective Java》,有几点需要注意:

1. 使用 == 检查 引用是否相等,引用相等就直接返回 true了,因为内存地址都一样了,具体内容也肯定一样,就不用比较了。

2. instanceOf 判断是否为正确的类型,如果不是,那么直接返回 false。都不是同一个类型的东西,就甭比较了。

3. 把需要比较的 Object 转换成该类(由于 instanceOf,所以肯定能转换的),转换之后,再对每个关键域进行比较。

1 和 2 都是为了性能考虑,3 就是真正的比较。

(完)



作者:鼬自来晓
链接:https://zhuanlan.zhihu.com/p/22208465
来源:知乎
著作权归作者所有。

                                                                                                                                                                                              

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:323次
    • 积分:35
    • 等级:
    • 排名:千里之外
    • 原创:3篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档