字符串常量池详解(jDK1.8)
例子
String a = new String("myString");(1)
String b = "myString";(2)
String c = "my" + "String";(3)
String d = c;(4)
String e = new String("my")+new String("String");(5)
String f = a.intern();(6)
System.out.print(a == b);//false
System.out.print(a == c);//false
System.out.print(b == c);//true
System.out.print(b == d);//true
步骤一:在创建"myString"字符串之前会先去字符串常量池查看是否存在"myString",如果不存在的话就在字符串常量池和堆区各创建一个"myString"。如果字符串常量池存在的话,就只在堆区创建一个。a对象的地址在堆区(字符串常量池之外的堆区,下面的堆区都是这个意思)
步骤二:在创建"myString"字符串之前会先去字符串常量池查看是否存在"myString",如果不存在的话就在字符串常量池创建一个"myString"。如果字符串常量池存在的话,就不创建,也就是说相同的字符串在字符串常量池只有一份,所有对象引用同一份,b对象的地址在堆区。
步骤三:当一个字符串有多个字符串常量连接而成,他自己肯定是字符串常量,所以c对象在编译的时候就优化成"myString",所以b和c的创建过程其实是一样的
步骤四:d和c指向同一地址。
步骤五: 一共会创建五个对象,堆区三个,字符串常量池两个。堆区会生成"myString"字符串,对象e指向这个字符串地址。其他四个看步骤一和二。所以对象e和a,b,c,d都不相等。
步骤五结果:
步骤六:先用equals()方法比较判断"myString"在字符串常量池中是否存在,存在返回常量池中的地址,不存在返回堆中的地址
所以现在有一个方法可以展现步骤六地址的位置:
String e = new String("my")+new String("String");
String f = e.intern();
System.out.println("e==f? "+(e==f));//true
因为常量池中没有"myString"所以f指向e;
String b = "myString";
String e = new String("my")+new String("String");
String f = e.intern();
System.out.println("e==f? "+(e==f));//false
System.out.println("f==b? "+(f==b));//true
因为常量池中因为String b = "myString"操作有了"myString"所以f指向b;