本篇重点(tips):
1. String Pool 是以Java 中 String 对象是不可变的这一特性为基础的
2. String Pool是Heap(堆)中的一块特殊空间(JDK 1.7 之前不是,是在PermGen里面,从1.7开始在heap里面了),存储不重复的String 常量
3. 用new关键字和用 "" 创建String 的方式有所不同。new 关键字每次都会在heap中创建一个新的String 对象, 用"" 创建(这种创建方式学名儿叫String Literal),如果String Pool中已经存在相同值的String 对象则直接返回。这两种方式创建的都是String Object.
实例讲解
line 1: String s = new String("A")
这是我们的第一行代码, 在String Pool中没有“A”这个常量, 所以会先在String Pool中创建“A”。 然后因为有new关键字, 也会在Heap 中也创建一个对象“A”,s指向heap中创建的“A”对象。 所以在这一步中创建了两个对象。如图:
line 2: String s1 = new String("A")
这时候String Pool 中已经有了对象“A”,String Pool中不再创建。 但因为new关键字,会在heap中再创建一个新的对象“A”, s1指向这个新创建的对象。如图:
line 3: String s2 = "A"
查看String Pool中有“A” , 直接指向它
line 4: String s3 = "B"
在String Pool中不存在“B”,在String Pool中创建“B”
line 5: String s4 = "A"
查看String Pool中有“A” , 直接指向它
最终如下图所示:
运行代码测试:
1 String s = new String("A"); 2 String s1 = new String("A"); 3 String s2 = "A"; 4 String s3 = "B"; 5 String s4 = "A"; 6 7 System.out.println("s == s1:"+(s == s1)); 8 System.out.println("s == s2:"+(s == s2)); 9 System.out.println("s1 == s2:"+(s1 == s2)); 10 System.out.println("s2 == s4:"+(s2 == s4)); 11 System.out.println("s2 == s3:"+(s2 == s3));
结果:
s == s1:false s == s2:false s1 == s2:false s2 == s4:true s2 == s3:false
注意line 7~line 11, 比较操作要加上() 哦, 第一次跑的时候没加,结果都是false,仔细看了一下才想起来,算数运算符的优先级高于比较运算符。有时候我们知道一件事,但应用中还是容易忽略。
结论:
所以尽量还是使用""(Literal)的方式创建String, 这样值相同的String使用Pool中这一个对象, 节省空间。这个做法学名儿又叫String interning。