
本文深入解析 Java 中 == 运算符对 String 类型的实际行为,阐明其本质是引用比较而非内容比较,并结合字符串常量池、编译期优化与运行时对象创建机制,清晰解释为何 str1 == str2 为 true 而 str1 == str4 为 false。
本文深入解析 java 中 `==` 运算符对 string 类型的实际行为,阐明其本质是引用比较而非内容比较,并结合字符串常量池、编译期优化与运行时对象创建机制,清晰解释为何 `str1 == str2` 为 true 而 `str1 == str4` 为 false。
在 Java 中,== 运算符永远不比较字符串内容,它只判断两个引用是否指向堆(或字符串常量池)中的同一内存地址。理解这一行为的关键,在于掌握 Java 的字符串常量池(String Pool)机制和不同字符串创建方式的底层差异。
✅ 字符串字面量自动入池:str1, str2, str6 指向同一对象
当使用双引号直接声明字符串(如 "Object"),JVM 会在编译期将该字面量放入字符串常量池,并在运行时复用已存在的相同内容对象:
String str1 = "Object"; // 编译期入池 String str2 = "Object"; // 复用 str1 的池中引用 → str1 == str2 为 true String str6 = "Obj" + "ect"; // 编译期常量折叠(constant folding),等价于 "Object" → 同样复用池中对象
因此 str1 == str2、str1 == "Object"、str1 == str6 全部返回 true —— 它们本质上是同一个 String 实例的多个引用。
❌ new String() 强制新建对象:str3 独立于常量池
String str3 = new String("Object"); // 在堆中新建对象,即使内容相同也不入池(除非显式调用 intern())new 关键字绕过字符串常量池,总是在堆内存中分配新空间,因此 str1 == str3 必然为 false。
立即学习“Java免费学习笔记(深入)”;
⚠️ substring() 和动态拼接默认不入池:str4, str5 是独立对象
关键点来了:name.substring(0, 6) 是运行时方法调用,其返回值默认不会自动放入字符串常量池(Java 7u6 之后 substring 不再共享底层数组,且结果未被 intern):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
String name = "Object Oriented"; String str4 = name.substring(0, 6); // 返回新 String 对象,内容为 "Object",但不在池中 String str5 = name.substring(0, 6); // 再次调用 → 新建另一个独立对象
所以 str4 == str5 为 false(两个不同堆对象),str1 == str4 也为 false(池中对象 vs 堆中对象)。可通过 str4.intern() 显式将其加入常量池,此时 str1 == str4.intern() 才为 true。
? 验证引用地址:用 System.identityHashCode() 辅助调试
以下代码可直观验证内存地址差异:
System.out.println(str1 + "==" + str4 + " | "
+ System.identityHashCode(str1) + "==" + System.identityHashCode(str4)
+ ": " + (str1 == str4));
// 输出类似:Object==Object | 225991731==1308244637: falseidentityHashCode 可近似反映对象内存地址(即使对象被移动,该值也保持不变),明显不同的哈希值即证明它们是不同对象。
✅ 正确做法:内容比较永远用 equals()
无论字符串如何创建,只要需判断逻辑相等性,请始终使用:
if (str1.equals(str4)) { ... } // ✅ 安全、语义正确
if (str1 == str4) { ... } // ❌ 危险!仅适用于确定同源字面量的极少数场景注意:equals() 会先快速判空和引用相等(==),再逐字符比较,因此对相同对象效率极高;而 == 的误用是 Java 初学者最常见 bug 来源之一。
总结一句话:== 比的是“是不是同一个东西”,equals() 比的是“内容是不是一样”——前者依赖 JVM 内存管理策略,后者才是业务逻辑所需的语义比较。

















