You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何相同值的String未指向字符串常量池中的同一对象?

关于字符串常量池与String对象指向的疑惑解答

嘿,这个问题我刚入门Java的时候也踩过坑!先帮你捋清楚核心原因——你看到的s2没有指向常量池已有对象的情况,大概率是因为创建s2时用了new String("Hello"),而不是直接用双引号声明。

咱们一步步拆解细节:

  • 当你用s1 = "Hello"这种双引号直接赋值时,JVM会先去字符串常量池里查找是否存在值为"Hello"的对象:
    • 如果不存在,就会在常量池里创建这个对象,再让s1指向它;
    • 如果已经存在(比如之前s1已经创建过),就直接让新引用指向这个已有的常量池对象。
  • 但如果是用s2 = new String("Hello")来创建,逻辑就完全不同了:
    • JVM会先检查常量池里有没有"Hello",如果没有就先在常量池创建一个;
    • 然后一定会在堆内存里新建一个String对象,这个堆对象的内部会引用常量池里的"Hello",最后让s2指向堆里的这个新对象,而非常量池里的那个。
  • 你提到的s3能指向已有对象,应该就是用了s3 = "Hello"这种直接赋值的方式,所以它会直接复用常量池里的"Hello",和s1指向同一个对象。

举个代码例子更直观:

String s1 = "Hello"; // 常量池创建"Hello",s1指向它
String s2 = new String("Hello"); // 堆里新建对象,s2指向堆对象
String s3 = "Hello"; // 直接复用常量池的"Hello",s3和s1指向同一个对象

System.out.println(s1 == s3); // 输出true,因为指向同一个常量池对象
System.out.println(s1 == s2); // 输出false,因为s1指向常量池,s2指向堆对象

另外补充个小知识点:如果想让new String("Hello")也复用常量池的对象,可以调用intern()方法,比如s2 = new String("Hello").intern();,这时候s2就会指向常量池里的"Hello"了。

内容的提问来源于stack exchange,提问作者user9608350

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:44:53