常量:以""号包裹的都是常量;
String s1,s2,s3,s4,s5,s6,s7,s8这样的都是变量;
//正常的代码
String s1="javatest";
String s2="java";
String s3="test";
String s4=s2+s3;
String s5=s2+"test";
String s6="java"+s3;
String s7="java"+"test";
System.out.println(s1==s4);//false
System.out.println(s1==s5);//false
System.out.println(s1==s6);//false
System.out.println(s1==s7);//true
System.out.println(s4==s5);//false
System.out.println(s5==s6);//false
System.out.println(s6==s7);//false
String s8=s6.intern();
System.out.println(s1==s8);//true
//编译后的代码
String s1 = "javatest";
String s2 = "java";
String s3 = "test";
String s4 = s2 + s3;
String s5 = s2 + "test";
String s6 = "java" + s3;
String s7 = "javatest";
为啥会是这样的结果呢?
我们可以看到编译后,常量与常量的结果还是在常量池中,编译的时候优化了,
s7就把这2个常量拼接到一块了,所以s1==s7为true;
在编译后带有一个变量的字符串,没有给到拼接到一起,反而在堆中创建了一个新的数据,
底层使用了new StringBuilder,所以s1==s4,s1==s5,s1==s6为false,
可以通过jclasslib去看字节码指令就能明白了;
s8就是使用了intern()方法,去在字符串常量池有了这个数据,直接返回这个数据的地址,
所以s1==s8为true;
final String a="hello"; final String b="word"; String c=a+b; String d="helloword"; System.out.println(c==d);//true 被final修饰的字符串a ,b 这时候就不是变量了,而是引用,在编译期优化了,可以通过字节码指令看到详细信息,所以c==d为true