Java中的equals()和hashCode() - 超详细篇

c0836b5617c6bb54bb2ffc01ff2ee28

前言

大家好啊,我是汤圆,今天给大家带来的是《Java中的equals()和hashCode() - 详细篇》,希望对大家有帮助,谢谢

文章纯属原创,个人总结难免有差错,如果有,麻烦在评论区回复或后台私信,谢啦

比个耶

简介

说到equals和hashCode,首先要说下Object

我们都知道,这个Object是Java所有类的超类,其他类都是从Object直接或间接继承而来的

而Object中自带的equals和hashCode方法就是今天我们要谈论的话题

目录

什么是equals()方法

什么是hashCode()方法

equals和hashCode有啥关系

等等

正文

PS:正文可能比较长,有点像是一层层在剥洋葱,所以会显得有点啰嗦,需要看结论的可以直接跳到文末看总结

传送

什么是equals方法

equals方法用来比较两个对象的属性是否相等,也可以说是比较两个引用对象是否为同一个对象(因为Object中的equals就是这个意

思,如果你没有覆写equals方法,那么就可以这么说)

因为在Object中没有属性,所以就只比较了两个引用指向的对象是否相等

只要对象不相等,那么就返回false(其实这样对子类来说是很不友好的,太绝对了,请往下看)

代码如下所示:

public class Object { public boolean equals(Object obj) { // 可以看到,官方括号的写法很规范(向老人家学习) return (this == obj); } }

但是我们平时在定义类时,都或多或少会包含几个属性

比如下面的例子

public class EqualsDemo { private int m; // 省略 getter,setter,constructor(m) public static void main(String[] args) { EqualsDemo demo1 = new EqualsDemo(1); EqualsDemo demo2 = new EqualsDemo(1); // 这里期望返回true,实际却是false System.out.println(demo1.equals(demo2)); } // 这里延续Object的写法,只单纯地比较两个引用指向的对象是否相等 @Override public boolean equals(Object o) { return this == o; } }

其中定义了一个基本类型的属性 int m;

然后两个实例 demo1 和 demo2 都拥有相同的属性 m = 1;

但是equals方法却返回false

原因就是,equals方法没有正确地编写

equals怎么才算正确编写呢?

我们应该把属性也进行比对,而不是单纯地比较对象的引用

(这就好比我们选一半,不能只看外在,而是要外在内在一起看,那样就。。。就都单着吧)

单身

修正后的代码如下所示:

public class EqualsDemo { private int m; // 省略 getter,setter,constructor(m) public static void main(String[] args) { EqualsDemo demo1 = new EqualsDemo(1); EqualsDemo demo2 = new EqualsDemo(1); // 这时就会返回true System.out.println(demo1.equals(demo2)); } @Override public boolean equals(Object o) { if (this == o) return true; // 加了下面这两行,对属性进了比对 EqualsDemo that = (EqualsDemo) o; return m == that.m; } }

上面看起来好像没什么问题了,但是实际运行却很容易出现空指针异常或者类型转换异常

因为equals方法中,我们在强转之前没有对参数 o 进行检查

检查什么呢?

检查两个地方:

首先要确保o不能为空null

其次确保o是EqualsDemo类或者子类(父类行不行?不行,父类没有子类特有的属性,强转还是会报错)

代码如下:

public class EqualsDemo { private int m; // 省略 getter,setter,constructor(m) public static void main(String[] args) { EqualsDemo demo1 = new EqualsDemo(1); EqualsDemo demo2 = new EqualsDemo(1); System.out.println(demo1.equals(demo2)); } @Override public boolean equals(Object o) { if (this == o) return true; // 加了这一行判断 if (!(o instanceof EqualsDemo)) return false; EqualsDemo that = (EqualsDemo) o; return m == that.m; } }

上面用到了instanceof来判断(别,我知道你要说啥,朋友咱先往下看)

img

instanceof的用法是 A instanceof B,用来判断A是否为B类或者B的子类

这样就可以防止空指针和转换异常的出现

所以equals判断的内容总结下来就是三步

判断两个引用指向的对象是否相等

判断传来的参数是否为当前类或者当前类的子类

比较各个属性值是否相等

如果属性是对象的引用,那第三步该怎么比呢?

那就有点像套娃了(什么?没听过套娃?强烈推荐你去看陈翔六点半,里面有很多套娃的案例【您的账户已到账0.5毛】

到账

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydjyp.html