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

Java字符串字面量拼接机制、对象创建位置及池化问题解析

Java字符串拼接与常量池问题解析

一、字符串拼接的两种场景与对象创建规则

Java里字符串拼接分两种情况,对象创建的位置和逻辑完全不同:

  • 编译期可确定的字面量拼接:比如直接写"ja" + "va",编译器会自动优化成完整的"java",这个字符串对象会被创建在字符串常量池中(属于方法区的一部分),而且常量池里不会存在重复的字面量,只会保留一份。
  • 运行时动态拼接(变量参与的拼接):如果拼接的是变量(比如代码里的b + c),编译期没法确定最终结果,运行时会通过StringBuilder的append方法拼接,最后调用toString()生成新的String对象——这个对象是创建在堆内存里的,不会自动进入字符串常量池。

二、代码运行结果分析

先看给出的代码:

class StringClass {
    public static void main(String[] args) {
        String a = "java";
        String b = "ja";
        String c = "va";
        String d = b + c;
        System.out.println(a == d);
    }
}

逐行拆解逻辑:

  • String a = "java";:直接从字符串常量池获取(或创建)"java"对象,a指向常量池中的这个对象引用。
  • String b = "ja";和String c = "va";:同理,b、c分别指向常量池中的"ja"、"va"对象。
  • String d = b + c;:因为b和c是变量,编译期无法确定拼接结果,运行时会执行以下逻辑:
    1. 新建StringBuilder对象
    2. 调用append(b)和append(c)完成拼接
    3. 调用toString()生成新的String对象,这个对象存放在堆内存中,d指向堆上的这个引用。
  • System.out.println(a == d);:==在Java中比较的是对象的引用地址,a指向常量池的"java",d指向堆上的"java",两者地址不同,所以返回false。

三、关于常量池的疑问解答

你提到的“若变量a和d都属于字符串常量池”是错误的——d指向的对象不在字符串常量池里,只有编译期确定的字面量或手动调用intern()方法的字符串才会进入常量池。如果想让d指向常量池的对象,可以修改代码为String d = (b + c).intern();,此时a == d会返回true。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:05:00