钩子:看着一样,== 却说 false
String s1 = "橙码酱";
String s2 = new String("橙码酱");
System.out.println(s1 == s2); // false !
System.out.println(s1.equals(s2)); // true
内容明明一样,== 却说它们不相等。为什么?
核心:== 比地址,equals 比内容
回想第 14 篇:变量存的是对象的地址(遥控器),不是对象本身。
- == 比较:两个遥控器是不是控制同一台机器(地址是否相同);
- equals 比较:两台机器里的内容是不是一样(默认比地址,但 String 等类重写过它,改成比内容)。
上面 s1 指向常量池里的"橙码酱",s2 指向堆里 new 出来的另一个"橙码酱"——两个不同的对象,地址不同,所以 == 是 false;但内容一样,equals 是 true。

三个必懂的坑
坑 1:比较字符串内容,永远用 equals
if (name == "admin") { ... } // 错误示范
if (name.equals("admin")) { ... } // 正确
坑 2:equals 的防空指针写法
// 如果 name 可能是 null:
if ("admin".equals(name)) { ... } // 把常量放前面,永远不会 NPE
name.equals("admin") 在 name 为 null 时直接抛 NullPointerException;反过来写就安全。这是新手线上事故的常客。
坑 3:什么时候 == 反而是对的?
基本类型(int、long、char…)没有对象、没有地址,== 比的就是值本身——这时候用 == 完全正确:
int a = 10;
if (a == 10) { ... } // ✔ 基本类型用 ==
记住分界线:基本类型比值用 ==,对象比内容用 equals。
一个加分知识:常量池
String a = "橙码酱";
String b = "橙码酱";
System.out.println(a == b); // true !
字面量字符串存在常量池里,相同的字面量共用一个对象(第 21 篇说过,这只有在 String 不可变的前提下才成立)。所以 a 和 b 地址相同,== 是 true——但这只是"恰好相等",判断内容依然永远写 equals,这是习惯问题。
本文示例代码均已本地实测通过,可直接运行。
对应文件:EqualsDemo.java
橙码酱,分享更有用的技术知识,助你成为更优秀的开发者。