大家好啊,我是汤圆,今天给大家带来的是《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来判断(别,我知道你要说啥,朋友咱先往下看)
instanceof的用法是 A instanceof B,用来判断A是否为B类或者B的子类
这样就可以防止空指针和转换异常的出现
所以equals判断的内容总结下来就是三步:
判断两个引用指向的对象是否相等
判断传来的参数是否为当前类或者当前类的子类
比较各个属性值是否相等
如果属性是对象的引用,那第三步该怎么比呢?
那就有点像套娃了(什么?没听过套娃?强烈推荐你去看陈翔六点半,里面有很多套娃的案例【您的账户已到账0.5毛】)