
你是不是也遇到过这种情况?明明两个字符串的内容一模一样,用 if (str1 == str2) 判断时,程序却无情地走进了 else 分支。
作为一个 Java 新手,这个问题曾困扰了我很久。今天我们来扒一扒这背后的原理,保证你看完后再也不会写错!
先看一段简单的代码:
String str1 = new String("hello");
String str2 = new String("hello");
if (str1 == str2) {
System.out.println("它俩是一样的!");
} else {
System.out.println("它俩不一样!"); // 结果竟然打印了这行?
}按照我们的直觉,str1 和 str2 都是 "hello",应该一样才对。为什么 Java 告诉我它们不一样?
在 Java 的世界里,比较东西分两种情况。
A. == 操作符:比较的是“地址” (内存地址)
这就好比在问:“你们拿的是不是同一把家门钥匙?”
在上面的代码中,我们用了 new 关键字。new 的意思是在内存堆(Heap)里开辟一块新地盘。
str1 住在一个地址(比如 0x111)。
B. equals() 方法:比较的是“内容” (逻辑值)
这就好比在问:“你们的房子装修是不是一样的?”
如果我们换成 equals:
if (str1.equals(str2)) {
System.out.println("它俩内容一样!"); // 打印这行
}String 类重写了 equals 方法,它会逐个字符去比较。只要字面一样,就返回 true。
这里有个坑。如果你不用 new,而是这样写:
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // 这里竟然是 true!这是因为 Java 为了省内存,做了一个优化。当你直接写 "hello" 时,Java 会先去“字符串常量池”找有没有这个字。如果有,直接把地址给你;如果没有,才创建一个。
所以这里 s1 和 s2 确实拿的是同一把钥匙。
但千万别依赖这个!在实际开发中,数据往往是从数据库或者网络传来的,你无法保证它们在常量池里。
为了避免半夜调 Bug,请记住这条铁律:
在 Java 中,比较基本数据类型(int, boolean 等)用 ==; 比较对象(String, Integer, 自定义对象),永远使用 .equals()!
小技巧 (Pro Tip):
为了防止空指针异常(NullPointerException),建议把常量写在前面:
if (userStatus.equals("ACTIVE")) (如果 userStatus 是 null,程序会崩)
if ("ACTIVE".equals(userStatus)) (安全!)