equals 与 == 的区别
==与equals的主要区别是:==常用于比较原生类型,而equals()方法用于检查对象的相等性。另一个不同的点是:如果
==和equals()用于比较对象,当两个引用地址相同,==返回 true。而equals()可以返回 true 或者 false 主要取决于重写实现。最常见的一个例子,字符串的比较,不同情况==和equals()返回不同的结果。
两点结论正确但偏薄。要答出深度,需要补三块:字符串常量池这个经典案例的完整推演、equals 重写必须连带重写 hashCode 的契约、以及 Integer 缓存这类包装类的陷阱。
语义层:值比较 vs 引用比较
==是运算符:基本类型比较值;引用类型比较引用(地址)——即”是不是同一个对象”equals是 Object 的方法:默认实现就是this == obj(比引用);语义由重写者定义,String、Integer、LocalDate 等都重写为”内容相等”
所以”equals 比内容”不是语言保证,而是类的契约承诺;自己写的类不重写 equals,equals 就退化为 ==。
字符串案例完整推演
String a = "hello"; |
JDK7 后常量池在堆中,intern 语义为”池中有则返回池引用,无则入池并返回”。理解常量池,才能解释为什么字面量 == 为 true 而 new 出来为 false。
重写 equals 的契约与 hashCode 连带
equals 重写必须满足:自反、对称、传递、一致、对 null 返回 false。而重写 equals 必须同时重写 hashCode,契约是:equals 相等的对象 hashCode 必须相等。
违反的后果直接体现在哈希容器:
class Point { int x, y; /* 只重写 equals,未重写 hashCode */ } |
HashMap 先比 hashCode 定位桶、再比 equals 定位节点;hashCode 不一致时 equals 根本没机会执行。这就是”equals 与 hashCode 是同一个契约的两面”。
包装类与缓存陷阱
Integer i1 = 127, i2 = 127; |
同理 Long/Short/Byte/Character 也有缓存区间。结论:对象比较永远用 equals(或 Objects.equals 防 NPE),== 只用于基本类型与判 null/单例身份。
实践清单
- 比较用
Objects.equals(a, b):null 安全,避免 NPE - IDE 生成 equals/hashCode 成对重写,字段选取与业务一致性定义一致
- 作为 Map key / Set 元素的类必须不可变或保证 hashCode 稳定(可变对象改字段后”从集合中消失”是经典 bug)
- 枚举比较可用 ==(单例语义),但统一用 equals 也无害且更安全
== 与 equals 的区别,表层是运算符与方法,里层是引用语义与内容语义的分工;而 hashCode 契约、常量池、包装类缓存这三个细节,决定了这个知识点在真实代码里会不会咬人。











