结构图:
java
public static void test1() { String str1 = "abc"; String str2 = "abc"; System.out.println(str1==str2); System.out.println(str1==str2.intern()); System.out.println(str1.intern()==str2.intern()); }
结果:true,true,true
数组
例2 :
结构图:
spa
public static void test1() { String str1 = "abc"; String str2 = new String("abc"); System.out.println(str1==str2); System.out.println(str1==str2.intern()); System.out.println(str1.intern()==str2.intern()); }结果:false,true,true
例3:
结构图:
code
public static void test3() { String str1 = new String("abc"); String str2 = new String("abc"); System.out.println(str1==str2); System.out.println(str1==str2.intern()); System.out.println(str1.intern()==str2.intern()); }
结果:false,false,true 对象
结果说明:
若是变量直接引用常量池的字符串,那么结果就会一致。但若是变量引用对象是一个字符串实例,而该实例才去引用常量池的字符串,那么比较的结果就不一致。而使用方法intern,就是去取得常量池中的引用
扩展:---------------------------------- 内存
第一点: 字符串
在jdk6中,字符串由三部分组成:char[] , offset , count。由于这样的结构致使在使用String.substring这个方法时可能发生内存泄漏例: string
String str1 = "abcd...." //假设str1有1万个字符,同时char[]的长度也有1万 String str2 = str1.substring(0,1) //str2只想要一个字符,但substring方法并无建立出一个新的字符串常量, //只是在str1基础上改变了它的偏移量,这彷佛看起来很不错,由于str1与str2共用char[]节约了内存。 str1 = null; //这时释放了str1,可是str1的实例并不会被GC回收,由于str2占有着它,而str2理论上 //应该只有1字符大小的空间,但实际不是,它占着一万个字符大小的内存.而在jdk7中它的结构变了,去掉了offset 与count 两项,String内容由char[]决定,而数组自己也表明了String的值
第二点: class
在jdk6中String常量池是放在perm中,而jdk7中常量池是放在堆中。GC在进行Full GC(不常常触发)才会回收perm的内存空间,可是堆的回收(特指年轻代)倒是比较常常发生的
test