equals()比较内容是否相同,==比较引用是否指向同一内存地址;字符串常量池使字面量==可能为true,但new创建的字符串==几乎总为false,equals()才是安全的内容比较方式。

Java 中用 equals() 比较字符串内容是否相同,用 == 比较两个引用是否指向同一块内存地址——这是最核心的区别。
字符串常量池让 == 有时“碰巧”为 true
当你写 String a = "hello"; String b = "hello";,a 和 b 都指向字符串常量池中同一个 "hello" 对象,此时 a == b 返回 true。但这是常量池优化的结果,不是语义上的相等判断。
一旦涉及运行时创建(比如 new String("hello") 或拼接、输入读取),对象就不再在常量池中,== 就几乎总是 false,哪怕内容一模一样。
String s1 = "abc";-
String s2 = "abc";→s1 == s2是 true(共享常量池) -
String s3 = new String("abc");→s1 == s3是 false(堆上新对象) -
s1.equals(s3)是 true(内容一致)
equals() 是安全的内容比较方式
String.equals() 内部先检查是否为同一对象(用 == 快速返回),再逐字符比对内容。它不关心对象在哪,只关心“长得一样不一样”。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
注意:调用 equals() 前最好判空,避免 NullPointerException。更稳妥写法是把字面量放前面:
-
"hello".equals(str)—— 即使str为null也安全 -
str.equals("hello")—— 若str为null,直接抛异常
什么时候真需要 ==?极少,但存在
绝大多数业务场景下,你想要的是“内容相等”,该用 equals()。只有极少数情况关注对象身份,比如:
- 做轻量级标识符缓存(如枚举式字符串管理)
- 性能敏感且能确保字符串都来自常量池或已 intern() 过
- 某些框架内部做引用快速校验(如 Spring 的 Bean 名称匹配)
普通开发中,把 == 用于字符串逻辑判断,基本等于埋雷。
小技巧:intern() 可以强制进常量池
new String("abc").intern() 会返回常量池中已有的 "abc" 引用(若存在),否则放入并返回。这时它可能和字面量字符串 == 成立:
String s1 = "abc";String s2 = new String("abc").intern();-
s1 == s2→ true
但除非有明确设计需求,不建议靠 intern() 来绕过 equals(),它会增加 GC 压力,且行为依赖 JVM 实现细节。

















