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

Java中字符串字面量拼接后使用==比较结果为何不同?

为什么两种字符串拼接场景下==比较结果不同?

这个问题的核心在于Java字符串编译期优化和运行期字符串拼接的区别,以及字符串常量池的工作机制,咱们一步步拆解:

1. 编译期常量拼接:直接复用常量池对象

先看返回true的代码:

public class Main {
    public static void main(String[] args) {
        String A = "hel" + "lo";
        String B = "lo";
        String C = "hel" + "lo";
        System.out.println(A == C); // true
    }
}

这里的"hel" + "lo"都是字符串字面量,Java编译器在编译阶段会自动将这种字面量拼接优化成完整的"hello",并且会把这个字符串存入字符串常量池(String Pool)。

当创建变量A和C时,它们都会直接指向常量池里同一个"hello"对象,所以用==比较引用地址时,结果自然是true。

2. 运行期变量拼接:生成新的堆对象

再看返回false的代码:

public class Main {
    public static void main(String[] args) {
        String A = "hel" + "lo";
        String B = "lo";
        String C = "hel" + B;
        System.out.println(A == C); // false
    }
}

这里的"hel" + B中,B是一个字符串变量(哪怕它的值是字面量"lo"),编译器在编译阶段无法确定B的最终值(比如运行时B可能被修改),所以这种拼接会在运行阶段执行:
Java会创建一个StringBuilder对象,先append"hel",再append B的值,最后调用toString()生成一个新的String对象——这个对象是存在堆内存中的,而不是字符串常量池里。

而A指向的是常量池里的"hello",两者是不同的对象,所以==比较引用地址时返回false。

补充:如何让变量拼接也复用常量池对象?

如果把B用final修饰,变成编译期常量:

public class Main {
    public static void main(String[] args) {
        String A = "hel" + "lo";
        final String B = "lo"; // 用final修饰,变成编译期常量
        String C = "hel" + B;
        System.out.println(A == C); // true
    }
}

此时编译器能确定B的值不会改变,会把"hel" + B优化成"hello",C也会指向常量池里的同一个对象,==就会返回true。

关键提醒

永远记住:==比较的是对象的引用地址,如果要比较字符串的内容,应该使用equals()方法,比如A.equals(C)在两种场景下都会返回true。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 20:52:30