代码
package day12;
public class StringTest9 {
public static void main(String[] args) {
String s1 = "mysql";
String s2 = "mysql";
String s3 = "m" + "y" + "s" + "q" + "l";
String s4 = "my" + new String("sql");
String s5 = new String("mysql");
String s6 = "" + s5;
String s7 = "" + s5;
System.out.println(s1==s2);//true
System.out.println(s1==s3);//true
System.out.println(s1==s4);//false
System.out.println(s1==s5);//false
System.out.println(s1==s6);//false
System.out.println(s4==s5);//false
System.out.println(s4==s6);//false
System.out.println(s5==s6);//false
System.out.println(s6==s7);//false
}
}
分析
String类是final修饰的,以字面量的形式创建String变量时,jvm会在编译期间就把该字面量("mysql")放到字符串常量池中,由Java程序启动的时候就已经加载到内存中了。这个字符串常量池的特点就是有且只有一份相同的字面量,如果有其它相同的字面量,jvm则返回这个字面量的引用(地址),如果没有相同的字面量,则在字符串常量池创建这个字面量并返回它的引用(地址)。
由于s2指向的字面量"mysql"在常量池中已经存在了(s1先于s2),于是jvm就返回这个字面量绑定的引用(地址),所以s1和s2是相等的。
s3中字面量的拼接其实就是"mysql",jvm在编译期间就已经对它进行优化,所以s1和s3也是相等的。
new String("sql")生成了两个对象,一个存在常量池中,另一个存在堆中, s4实质上是两个对象的相加,编译器不会进行优化,相加的结果存在堆中,而s1存在字符串常量池中,所以s1和s4不相等。
s1存在字符串常量池中,s5存在堆中,所以不相等。
s1存在字符串常量池中,s6存在堆中,所以不相等。
s4(是相加的结果)在堆中,s5是在堆中new出来的,不相等。
s4(是相加的结果)在堆中,s6(是相加的结果)在堆中,不相等。
s6(是相加的结果)在堆中,s5是在堆中new出来的,不相等。
s6(是相加的结果)在堆中,s7(是相加的结果)在堆中,不相等。
参考资料
https://www.cnblogs.com/tongkey/p/8587060.html
https://blog.csdn.net/zm13007310400/article/details/77534349
https://blog.csdn.net/studyfordream2015/article/details/70199693