关于重写equals();

来源:互联网 发布:ugnx是什么软件 编辑:程序博客网 时间:2024/06/03 07:21
      

今天复习了下 《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
原创粉丝点击