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

Java 11中使用==比较字符串:为何case_1返回false?

字符串==比较的差异原因解析

先明确Java字符串常量池的核心规则:

  • 编译期能确定的字符串字面量(或常量表达式)会被放入字符串常量池,相同内容的字面量指向同一地址。
  • 运行期动态生成的字符串(无法在编译期确定内容)会直接在堆内存创建新对象,不会自动进入常量池。

代码与输出差异分析

代码示例

public class Main {
    public static void main(String[] args) {
        MyString ms = new MyString();

        String str1 = ms.getString1(10);
        String str11 = ms.getString1(10);

        String str2 = ms.getString2();
        String str22 = ms.getString2();

        String str3 = 10 + "";
        String str33 = 10 + "";

        System.out.println(str1 == str11); // case_1 输出false
        System.out.println(str2 == str22); // case_2 输出true
        System.out.println(str3 == str33); // case_3 输出true
    }
}

class MyString {
    String getString1(int n) {
        return n + "";
    }

    String getString2() {
        return 10 + "";
    }
}

预期与实际输出

预期输出:

true
true
true

实际输出:

false
true
true

分场景解释

  1. case_1:getString1(int n)的返回值
    getString1中的n + "",n是方法参数,其值只能在运行时确定。编译器无法提前知道n的具体数值,因此这段代码会在运行时通过StringBuilder拼接生成一个新的String对象,直接存放在堆内存(而非常量池)。每次调用getString1(10)都会生成一个全新的对象,所以str1和str11指向不同的堆地址,==比较地址返回false。

  2. case_2:getString2()的返回值
    getString2中的10 + ""是编译期可确定的常量表达式,编译器会直接将其优化为字面量"10",并放入字符串常量池。每次调用getString2()都会返回常量池中同一个"10"对象,因此str2 == str22返回true。

  3. case_3:10 + ""直接赋值
    main方法中的10 + ""同样是编译期可确定的常量表达式,编译器会直接替换为字面量"10",两次赋值都指向常量池中的同一对象,所以str3 == str33返回true。

验证补充

如果想让case_1返回true,可以调用String.intern()方法,将运行时生成的字符串加入常量池:

String str1 = ms.getString1(10).intern();
String str11 = ms.getString1(10).intern();
System.out.println(str1 == str11); // 输出true

intern()会检查常量池中是否存在相同内容的字符串,存在则返回常量池中的对象;不存在则将当前对象加入常量池并返回,因此两次调用后指向同一地址。

内容的提问来源于stack exchange,提问作者ko-hs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:07:08