【Java 每日一练 - Day2】== 和 equals 的区别?hashCode 和 equals 的关系?
·
哈喽,各位刷题小伙伴!Day1 的基本数据类型考点大家都掌握了吗?今天咱们直击 Java 面试高频核心题 ——== 和 equals 的区别,还有 hashCode 与 equals 的 “绑定关系”,这题几乎是面试必问,赶紧码住!
今日题目
- Java 中 == 运算符的作用是什么?
- equals 方法的默认实现和重写逻辑?
- hashCode 和 equals 之间有什么必须遵守的约定?
一、基础答案
- == 运算符的作用
-
- 比较 基本数据类型:比较的是 值是否相等(如 int a=10; int b=10; a==b → true);
-
- 比较 引用数据类型:比较的是 对象的内存地址是否相同(即是否指向同一个对象,如 String s1=new String("a"); String s2=new String("a"); s1==s2 → false)。
- equals 方法的本质
-
- 默认实现:Object 类中的 equals 方法底层就是 ==,即比较对象地址(源码:public boolean equals(Object obj) { return (this == obj); });
-
- 重写逻辑:大部分常用类(如 String、Integer)会重写 equals 方法,改为 比较对象的内容是否相等(如 String s1="a"; String s2="a"; s1.equals(s2) → true)。
- hashCode 与 equals 的约定(面试重点)
-
- 核心原则:如果两个对象 equals 相等,那么它们的 hashCode 必须相等;
-
- 反向不强制:如果两个对象 hashCode 相等,equals 不一定相等(哈希冲突场景)。
二、深度拆解(面试加分项)
1. 为什么 String 重写了 equals 和 hashCode?
看 String 类的核心源码(简化版):
public class String {
private final char value[];
// 重写equals:比较字符数组内容
public boolean equals(Object anObject) {
if (this == anObject) return true;
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i]) return false;
}
return true;
}
}
return false;
}
// 重写hashCode:根据字符内容计算哈希值
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
}
原因:String 常作为 HashMap 的 key,重写后:
- equals 保证 “内容相同的 String 视为同一个键”;
- hashCode 保证 “内容相同的 String 哈希值相同”,能快速定位到 HashMap 的同一个桶,提升查询效率。
2. 违反 hashCode 与 equals 约定的后果?
如果只重写 equals 不重写 hashCode,会导致:
class Person {
private String name;
public Person(String name) { this.name = name; }
// 只重写equals:认为名字相同就是同一个人
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name);
}
// 未重写hashCode:使用Object的默认实现(基于内存地址)
}
// 测试代码
Person p1 = new Person("张三");
Person p2 = new Person("张三");
HashMap String> map = new HashMap<>();
map.put(p1, "程序员");
System.out.println(map.get(p2)); // 输出null,而非"程序员"
后果:HashMap 中会把 p1 和 p2 视为两个不同的 key,导致数据查询异常,违背 “相同内容的对象应作为同一个键” 的预期。
三、面试避坑提醒
- 比较字符串内容优先用 equals,别用 ==(除非确认是常量池中的对象);
- 自定义类重写 equals 时,必须同时重写 hashCode,否则会影响 HashMap、HashSet 等集合的使用;
- 重写 hashCode 时,尽量保证 “equals 相等的对象,hashCode 一定相等;equals 不相等的对象,hashCode 尽量不同”(减少哈希冲突)。
四、今日打卡
评论区留下你的答案:以下代码输出什么?✅
String s1 = "Java";
String s2 = new String("Java");
String s3 = s2.intern();
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s2));
(提示:intern () 方法会将字符串存入常量池,返回常量池中的引用)
文末预告
Day3 预告:String、StringBuffer、StringBuilder 的区别?面试中如何回答性能对比和适用场景?明天不见不散~
更多推荐


所有评论(0)