
Java 中创建 String 对象有两种常见方式:用字符串字面量(如 "hello")和用 new 关键字(如 new String("hello"))。它们的关键区别在于内存分配位置和对象复用机制,直接影响性能与 == 判断结果。
字符串常量池 vs 堆内存:位置决定是否共享
字符串字面量("abc")在编译期就确定,JVM 会将其放入字符串常量池(位于方法区,JDK 7+ 后移到堆中,但逻辑仍独立管理)。同一字面量多次出现,只会创建一个对象,后续引用都指向池中已有实例。
而 new String("abc") 每次都会在堆内存中新建一个 String 对象,即使内容相同,也和常量池中的对象不是同一个实例。
-
String a = "abc"; String b = "abc";→a == b为 true(指向常量池同一地址) -
String c = new String("abc"); String d = new String("abc");→c == d为 false(堆中两个不同对象) -
a == c也为 false(常量池 vs 堆,地址不同)
intern() 方法:手动触发常量池检查与复用
String.intern() 会检查常量池中是否存在相同内容的字符串:
- 如果存在,直接返回池中引用;
- 如果不存在,将当前字符串对象(或其副本)加入池,并返回该引用。
例如:
String s1 = new String("hello").intern();String s2 = "hello";System.out.println(s1 == s2); // true
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
注意:JDK 7+ 中,intern() 对已存在于堆中的字符串,会把它的引用存入常量池;JDK 6 中则会复制一份到永久代,行为略有不同。
实际开发建议:优先使用字面量,慎用 new
除非有明确需求(比如需要两个内容相同但独立的 String 对象用于某些反射或安全校验场景),否则应避免 new String("xxx")。
- 字面量更高效:避免无谓的对象创建和 GC 压力
- 语义更清晰:表达“这是一个固定值”,而非“我要新建一个字符串”
- == 判断需谨慎:比较内容一律用
.equals(),不要依赖 ==
一个小验证技巧:看内存地址变化
可以用 System.identityHashCode() 粗略观察对象是否相同(它返回对象的哈希码,对同一对象始终一致):
String x = "test";String y = "test";String z = new String("test");System.out.println(System.identityHashCode(x)); // 和 y 相同System.out.println(System.identityHashCode(z)); // 和 x/y 不同
这比直接打印对象更直观,且不依赖 toString() 重写。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










