public static void main(String[] args) {
String str1 = "ABCD";
String str2 = "A" + "B" + "C" + "D";
String str3 = "AB" + "CD";
String str4 = new String("ABCD");
String tmp = "AB";
String str5 = tmp + "CD";
String str6 = getString() + "CD";
// 这里所有的比较equals 都是true 因为比较的是内容
System.out.println(str1 == str2);// true
System.out.println(str1 == str3);// true
System.out.println(str1 == str4);// false
System.out.println(str1 == str5);// false
System.out.println(str1 == str6);// false
}
public static String getString() {
return "AB";
}
通过jd-gui进行反向编译可以得到:
public static void main(String args[])
{
String str1 = "ABCD";
String str2 = "ABCD";
String str3 = "ABCD";
String str4 = new String("ABCD");
String tmp = "AB";
String str5 = (new StringBuilder(String.valueOf(tmp))).append("CD").toString();
String str6 = (new
StringBuilder(String.valueOf(getString()))).append("CD").toString();
System.out.println(str1 == str2);
System.out.println(str1 == str3);
System.out.println(str1 == str4);
System.out.println(str1 == str5);
System.out.println(str1 == str6);
}
public static String getString()
{
return "AB";
}
总结:
1.字符串常量在编译时期就可以确定当前的值,并且已经存储在常量池,也就是说(不管是"A"+"B"+"C+"D"还是"AB"+"CD",在经过编译阶段都已经变为"ABCD"),这里str1,str2,str3都是指向常量池里面的ABCD,所以他们的引用肯定是相同的.
2.使用new创建的对象是堆中地址,引用是堆中地址,因为str1是常量池中的ABCD的引用,所以str1!=str4
3.使用变量存储,或者使用方法返回值,在编译阶段是无法确定其中的值,意思就是在编译阶段,是无法确定tmp的值是多少,那就说str5,str6也是无法确定的,只有在运行期才能确定,通过valueof()方法和append方法源码就可以确定,他们都是在执行new操作,(同2)所以肯定是和常量池中的ABCD的引用不等.