用 equals() 比较字符串内容,别用 ==;== 比较引用地址,equals() 比较内容且对 null 安全;equalsIgnoreCase() 用于忽略大小写;Objects.equals() 适用于不确定类型或需统一处理 null 的场景。

用 equals() 比较字符串内容,别用 ==
Java 中字符串比较最常见错误:用 == 判断两个字符串是否“相等”。== 比较的是引用地址,不是内容。即使两个字符串字面值完全一样,如果来自不同对象(比如一个来自字面量池、一个用 new String() 创建),== 就会返回 false。
正确做法是始终用 String.equals() 方法:
String a = "hello";
String b = new String("hello");
System.out.println(a == b); // false
System.out.println(a.equals(b)); // true
-
equals()会逐字符比对内容,区分大小写 - 它会先检查参数是否为
null,所以传null不会抛NullPointerException(但返回false) - 如果确定左操作数非空,也可以写成
"literal".equals(variable),避免变量为null时 NPE
equalsIgnoreCase() 用于忽略大小写的比较
当业务允许大小写不敏感时(比如用户名登录、配置项匹配),用 String.equalsIgnoreCase() 更安全直接:
String input = "HTTP";
System.out.println(input.equals("http")); // false
System.out.println(input.equalsIgnoreCase("http")); // true
- 内部逻辑和
equals()类似,只是把每个字符转成小写再比 - 同样对
null参数返回false,不会 NPE - 不要自己写
str.toLowerCase().equals(other.toLowerCase())—— 效率低、还可能在某些 locale 下出错(比如土耳其语的i大小写规则特殊)
需要性能或常量校验时才考虑 ==
== 并非完全没用,但它只适用于明确知道两个字符串是“同一对象”或“都来自字符串常量池”的场景:
立即学习“Java免费学习笔记(深入)”;
- 字面量字符串自动入池:
"abc" == "abc"是true - 调用
String.intern()后可强制入池,之后可用==安全比较(但代价是 GC 压力和 intern 表锁竞争,慎用) - 枚举字符串、配置常量、HTTP 方法名等固定值,在确认来源可控的前提下,有人用
==做快速判断(如method == GET),但前提是这些变量本身是 final 且指向 interned 字符串
绝大多数业务代码里,你不需要也不该依赖 == 来做语义相等判断。
注意 Objects.equals() 的通用兜底能力
当你不确定两个对象是否为 String(比如参数类型是 Object),或想统一处理 null 场景,可以用 java.util.Objects.equals():
String a = null; String b = "test"; System.out.println(Objects.equals(a, b)); // false,不抛异常 System.out.println(Objects.equals(a, null)); // true
- 它内部就是先判空再调用
.equals(),语义清晰、无副作用 - 适用于泛型方法、DTO 字段比较、单元测试断言等场景
- 不要为了“看起来更通用”而在已知是
String的地方强行套用——多一次方法调用,无实质收益
真正容易被忽略的点是:很多人记住了“用 equals”,却忘了检查调用方是否为 null;而另一些人过早优化,用 == 替代 equals(),结果在某次构建或 JVM 参数变更后突然出错——因为字符串是否入池、是否被 JIT 优化,有时并不稳定。










