关于重写equals();

转载 2016年08月28日 15:33:14
      

今天复习了下 《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
来源:知乎
著作权归作者所有。

                                                                                                                                                                                              

相关文章推荐

winform 重写Equals源码

重写equals方法

  • 2013-08-21 12:21
  • 48KB
  • 下载

关于重写equals方法,hashcode方法,toString方法 ,compareto()方法

关于重写equals方法,hashcode方法,toString方法 ,compareto()方法 总结: toString说白了,就是为了显示用的 Compareto 方法为了比较用的 只有...

重写toString和equals方法

  • 2013-06-04 21:28
  • 15KB
  • 下载

java重载与重写的区别+重写父类equals方法的完美实现

【0】README0.1) 本文章节【1】和【2】的内容转自 http://www.cnblogs.com/bluestorm/archive/2012/03/01/2376236.html ; ...

【Effective Java】Ch3_Methods:Item8_重写equals方法时遵循通用约定

虽然Object类是一个具体类,但它主要还是用于扩展。因为其所有nonfinal方法(equals、hashCode、toString、clone以及finalize)都是为重写设计的,所以这些方法都...

为什么在重写了equals()方法之后也必须重写hashCode()方法

我们都知道Java语言是完全面向对象的,在java中,所有的对象都是继承于Object类。Ojbect类中有两个方法equals、hashCode,这两个方法都是用来比较两个对象是否相等的。    ...

如何正确的重写equals() 和 hashCode()方法

本文将介绍在java中如何重写equals 和hashCode方法。 —译自:http://www.mkyong.com/java/java-how-to-overrides-equals-and-...
  • G0_hw
  • G0_hw
  • 2017-04-09 16:33
  • 162

Java:重写equals()和hashCode()

 Java:重写equals()和hashCode() (2012-06-01 09:00:11) 转载▼ 标签: 杂谈 分类: JAVA ...

如何正确的重写equals() 和 hashCode()方法

equals和hashCode重写技巧
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)