为何两段Java字符串代码的输出结果存在差异?
为什么两段字符串比较代码输出结果不同?
这是个非常经典的Java字符串常量池与编译期优化问题,我来给你拆解清楚:
先看输出true的代码
String s3="a"+"b"; String s4="ab"; if(s3==s4) { System.out.println("true"); } else { System.out.println("false"); }
这里的"a"+"b"属于编译期常量表达式,Java编译器在编译阶段会直接把它优化成最终的"ab"。当类加载时,s3和s4都会指向字符串常量池里的同一个"ab"对象。而==在比较引用类型时,判断的是两个变量是否指向同一个对象,所以这里会输出true。
再看输出false的代码
String s1="a"; String s2="b"; String s3=s1+s2; String s4="ab"; if(s3==s4) { System.out.println("true"); } else { System.out.println("false"); }
这里的s1+s2不是编译期常量——虽然s1和s2现在指向常量池的字符串,但它们是普通变量,编译器无法确保它们的值在运行时不会被修改,所以不会做编译期优化。实际运行时,这段拼接逻辑会通过StringBuilder的append()方法拼接,再调用toString()生成新字符串。而toString()方法会在堆内存中创建一个新的String对象,并不会指向常量池里的"ab"。
所以s3指向堆里的新对象,s4指向常量池里的对象,两个引用的地址完全不同,用==比较自然返回false。
额外小技巧:让第一段代码输出true
如果把s1和s2声明为final,它们就变成了编译期常量,此时s1+s2会被编译器优化成"ab",s3和s4就会指向同一个常量池对象:
final String s1="a"; final String s2="b"; String s3=s1+s2; String s4="ab"; System.out.println(s3==s4); // 输出true
内容的提问来源于stack exchange,提问作者rajkumar.11
相关产品推荐
相关产品推荐

