对象篇
模块化编程-自研模块加载器
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
public class EqualsMyClassExample {
public static void main(String[] args) {
Person u1 = new Person();
u1.setName(“Java”);
u1.setAge(18);
Person u2 = new Person();
u1.setName(“Java”);
u1.setAge(18);
// 打印 equals 结果
System.out.println(“equals 结果:” + u1.equals(u2));
}
}
class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
以上程序的执行结果,如下图所示:
因此通常情况下,我们要判断两个对象是否相等,一定要重写 equals 方法,这就是为什么要重写 equals 方法的原因。
2.hashCode 方法
=============
hashCode 翻译为中文是散列码,它是由对象推导出的一个整型值,并且这个值为任意整数,包括正数或负数。
需要注意的是:散列码是没有规律的。如果 x 和 y 是两个不同的对象,x.hashCode() 与 y.hashCode() 基本上不会相同;但如果 a 和 b 相等,则 a.hashCode() 一定等于 b.hashCode()。
hashCode 在 Object 中的源码如下:
public native int hashCode();
从上述源码可以看到,Object 中的 hashCode 调用了一个(native)本地方法,返回了一个 int 类型的整数,当然,这个整数可能是正数也可能是负数。
hashCode 使用
===========
相等的值 hashCode 一定相同的示例:
public class HashCodeExample {
public static void main(String[] args) {
String s1 = “Hello”;
String s2 = “Hello”;
String s3 = “Java”;
System.out.println(“s1 hashCode:” + s1.hashCode());
System.out.println(“s2 hashCode:” + s2.hashCode());
System.out.println(“s3 hashCode:” + s3.hashCode());
}
}
以上程序的执行结果,如下图所示:
不同的值 hashCode 也有可能相同的示例:
public class HashCodeExample {
public static void main(String[] args) {
String s1 = “Aa”;
String s2 = “BB”;
System.out.println(“s1 hashCode:” + s1.hashCode());
System.out.println(“s2 hashCode:” + s2.hashCode());
}
}
以上程序的执行结果,如下图所示:
3.为什么要一起重写?
===========
接下来回到本文的主题,重写 equals 为什么一定要重写 hashCode?
为了解释这个问题,我们需要从下面的这个例子入手。
3.1 Set 正常使用
============
Set 集合是用来保存不同对象的,相同的对象就会被 Set 合并,最终留下一份独一无二的数据。
它的正常用法如下:
import java.util.HashSet;
import java.util.Set;
public class HashCodeExample {
public static void main(String[] args) {
Set set = new HashSet();
set.add(“Java”);
set.add(“Java”);
set.add(“MySQL”);
set.add(“MySQL”);
set.add(“Redis”);
System.out.println(“Set 集合长度:” + set.size());
System.out.println();
// 打印 Set 中的所有元素
set.forEach(d -> System.out.println(d));
}
}
以上程序的执行结果,如下图所示:
从上述结果可以看出,重复的数据已经被 Set 集合“合并”了,这也是 Set 集合最大的特点:去重。
3.2 Set 集合的“异常”
===============
然而,如果我们在 Set 集合中存储的是,只重写了 equals 方法的自定义对象时,有趣的事情就发生了,如下代码所示:
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
public class EqualsExample {
public static void main(String[] args) {
// 对象 1
Persion p1 = new Persion();
p1.setName(“Java”);
p1.setAge(18);
// 对象 2
Persion p2 = new Persion();
p2.setName(“Java”);
p2.setAge(18);
// 创建 Set 集合
Set set = new HashSet();
set.add(p1);
set.add(p2);
// 打印 Set 中的所有数据
set.forEach(p -> {
System.out.println§;
});
}
}
class Persion {
private String name;
private int age;
// 只重写了 equals 方法
@Override
public boolean equals(Object o) {
if (this == o) return true; // 引用相等返回 true
// 如果等于 null,或者对象类型不同返回 false
if (o == null || getClass() != o.getClass()) return false;
// 强转为自定义 Persion 类型
Persion persion = (Persion) o;
// 如果 age 和 name 都相等,就返回 true
return age == persion.age &&
Objects.equals(name, persion.name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return “Persion{” +
“name='” + name + ‘’’ +
“, age=” + age +
‘}’;
对象篇
模块化编程-自研模块加载器