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
分场景解释
case_1:
getString1(int n)的返回值getString1中的n + "",n是方法参数,其值只能在运行时确定。编译器无法提前知道n的具体数值,因此这段代码会在运行时通过StringBuilder拼接生成一个新的String对象,直接存放在堆内存(而非常量池)。每次调用getString1(10)都会生成一个全新的对象,所以str1和str11指向不同的堆地址,==比较地址返回false。case_2:
getString2()的返回值getString2中的10 + ""是编译期可确定的常量表达式,编译器会直接将其优化为字面量"10",并放入字符串常量池。每次调用getString2()都会返回常量池中同一个"10"对象,因此str2 == str22返回true。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
相关产品推荐
相关产品推荐

