直接赋值创建1个常量池对象,new string()创建堆对象+常量池字面量共2个;==比较时直接赋值同内容地址相同,new出的对象地址不同;常量池字符串自动复用,new对象需调用intern()才入池。

Java 中 String 的构造方法(new String("xxx"))和直接赋值(String s = "xxx";)看似效果一样,实际在内存分配、对象数量、性能和比较行为上差异显著。
内存位置与对象数量不同
直接赋值时,JVM 会先检查字符串常量池中是否已存在该字面量。如果存在,直接复用;不存在,则在常量池中创建一份,并让变量指向它——只产生 1 个对象(位于方法区的常量池)。
而用 new String("xxx") 时,JVM 一定在堆内存中新建一个 String 对象;同时,字面量 "xxx" 本身也会进入常量池(如果尚未存在)。所以总共可能产生 2 个对象:1 个在常量池,1 个在堆中。
-
String a = "abc";→ 常量池中创建或复用 "abc" -
String b = new String("abc");→ 堆中新对象 + 常量池中"abc"(若未存在)
== 比较结果通常不同
== 比较的是引用地址。由于直接赋值的对象都指向常量池中的同一份数据,所以它们地址相同;而 new 出来的对象总是在堆中新开辟空间,地址必然不同。
-
String s1 = "hello"; String s2 = "hello";→s1 == s2为 true -
String s3 = new String("hello"); String s4 = new String("hello");→s3 == s4为 false -
s1 == s3也一定是 false(常量池 vs 堆)
字符串池(常量池)是否自动参与
直接赋值的字符串天然入池,可被后续同内容的直接赋值复用;构造方法创建的对象默认 不入池,即使内容相同也无法被自动复用。
如需手动入池,可调用 intern() 方法:
-
String s = new String("test").intern();→ 返回常量池中对应字符串的引用 - 之后再
String t = "test";,则s == t为 true
推荐使用场景
日常开发中,除非有明确需求(例如需要两个内容相同但独立的 String 实例),否则应优先使用直接赋值。
- 直接赋值更省内存、更快、符合 Java 字符串设计初衷
-
new String(...)多用于测试、反射、或某些特殊框架内部逻辑(如避免意外共享) - 注意:
new String(s).intern()是一种常见但冗余写法,等价于直接写s(若 s 已是常量池字符串)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











