equals比较内容是否相等,==比较是否指向同一内存地址;字符串字面量因常量池复用使"abc"=="abc"为true,但new string("abc")=="abc"为false;运行时构造的字符串必须用equals,且推荐"字面量".equals(str)或objects.equals()防空指针。

字符串比较时 equals 和 == 的行为差异
== 比较的是两个引用是否指向同一块内存地址,而 equals 比较的是字符串内容是否相等。Java 中字符串常量池会让字面量相同的 String 共享对象,但这只适用于编译期确定的字面量。
-
"abc" == "abc"返回true(常量池复用) -
new String("abc") == "abc"返回false(堆上新建对象,地址不同) -
new String("abc").equals("abc")返回true(内容一致)
如果变量来自用户输入、JSON 解析、数据库读取或任何运行时构造,它几乎肯定不是常量池里的对象,此时用 == 判断字符串相等会静默失败。
什么时候能安全用 == 判断字符串
只有在明确知道两个操作数都来自字符串字面量,或者都经过了 intern() 处理,且你确实需要判断“是否为同一个对象”时,== 才合理。
- 枚举值比较(如
MyEnum.VALUE == MyEnum.VALUE)可用==,因为枚举实例唯一 -
Objects.requireNonNull(str).intern() == "CONST"这类显式归一化后可考虑,但通常没必要 - 配置项或固定状态码(如
status == "SUCCESS")看似安全,但一旦 status 来自response.getBody()或map.get("status"),就不可靠
绝大多数业务代码里,“判断字符串内容是否相等”是真实需求,== 在这里不是“性能优化”,而是埋雷。
equals 调用前必须判空吗
必须。直接调用 null.equals("xxx") 会抛出 NullPointerException。常见错误写法:
-
str.equals("yes")—— str 为null时崩溃 -
"yes".equals(str)—— 推荐写法,左侧是字面量,不会空指针
更稳妥的方式是使用 Objects.equals(str, "yes"),它内部做了双端判空,语义清晰且无副作用。
Objects.equals(null, "yes") → falseObjects.equals("yes", null) → falseObjects.equals("yes", "yes") → true
注意:JDK 7+ 才有 Objects.equals,老项目若无法升级,就坚持把字面量放左边。
其他类型用 == 还是 equals
基本类型(int、boolean 等)只能用 ==;包装类(Integer、Boolean)要小心自动装箱带来的缓存陷阱:
-
Integer a = 127; Integer b = 127; a == b → true(缓存区间 -128~127) -
Integer a = 128; Integer b = 128; a == b → false(超出缓存,新对象)
所以对包装类,一律用 equals,除非你清楚自己在做什么。
自定义对象默认继承 Object.equals,只是地址比较,必须重写 equals(并配套 hashCode)才能按业务逻辑比较。
字符串判等这个点看着小,但它是 Java 里最常被误用、最难被测试覆盖到的坑之一——因为部分 case 碰巧通过,上线后某次数据格式微调就崩。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











