java字符串比较中,“==”比较引用(内存地址),equals比较字符内容;仅当指向同一对象实例时“==”才为true,如字面量赋值、intern()调用或同一对象赋值;equals逐字符比对,更安全,推荐用objects.equals()或字面量.equals()避免空指针。

Java中字符串比较,不能只看“==”还是“equals”,关键在于理解它们分别比什么:== 比的是引用(内存地址),equals 比的是字符内容。用错会导致逻辑错误,尤其在用户输入、配置判断、JSON解析等场景下极易踩坑。
什么时候 == 会返回 true?
只有当两个字符串变量指向**同一个对象实例**时,“==”才为 true。这通常发生在:
- 字符串字面量直接赋值(JVM 字符串常量池优化):String a = "hello"; String b = "hello"; → a == b 为 true
- 显式调用 intern() 且已存在相同内容:new String("hello").intern() == "hello" → true
- 同一个对象被多次赋值:String s = "test"; String t = s; → s == t 为 true
注意:通过 new String("xxx") 创建的字符串,即使内容相同,也一定不等于字面量或其他 new 出的对象(地址不同)。
为什么 equals 才是安全的内容比较方式?
equals 方法在 String 类中被重写,逐个字符比对内容,不依赖对象地址。只要字符序列完全一致(长度+每个 char 值相同),就返回 true。
- 推荐写法:str1 != null && str1.equals(str2)(避免空指针)
- 更稳妥写法:Objects.equals(str1, str2)(JDK7+,自动处理 null)
- 忽略大小写比较:str1.equalsIgnoreCase(str2)
不要写成 str2.equals(str1) 且 str2 可能为 null —— 这会抛 NullPointerException。
常见误用场景与修复建议
以下代码看似合理,实则危险:
- if (input == "quit") { ... } → 用户输入 new String("quit") 就失效
- if (status == "ACTIVE") → 数据库查出的字符串通常不是常量池对象
- return name == other.name;(在自定义类的 equals 中直接 == 比 String 字段)
统一改为:
- if ("quit".equals(input))(字面量在前,杜绝空指针)
- if ("ACTIVE".equalsIgnoreCase(status))
- 自定义类中:Objects.equals(this.name, other.name)
额外提醒:字符串拼接与常量池的关系
编译期可确定的字符串拼接会被优化进常量池:
- String a = "he" + "llo"; String b = "hello"; → a == b 为 true
- String x = "he"; String y = x + "llo"; → y == "hello" 为 false(运行期拼接,堆上新对象)
所以,不要依赖拼接结果是否在常量池——一律用 equals 判定语义相等。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











