代碼分析:官方說明翻譯:1.返回字符串對象的規(guī)范表示 2.字符串s調(diào)用intern時,如果常量池中有對象t滿足t.equals(s)==true,則返回t的地址;否則,將s的引用(即地址)加入常量池并返回s的引用
3.s.intern()==t.intern()的充分必要條件是s.equals(t)==true 注意:1.jdk1.6及以前版本的運行時常量池在方法區(qū)中,jdk1.7及以后版本的運行時常量池在堆中。 2.jdk1.6及以前版本會將字符串拷貝一份到運行時常量池,返回常量池中地址,jdk1.7及以后將堆上的地址引用復(fù)制到常量池,返回該引用地址。在此討論jdk1.7及以后版本。 一: String s1=new String("GY"); System.out.println(s1.intern()==s1);//false


如果常量池中有字符串對象"GY",則new String("GY")只創(chuàng)建一個堆中的對象;如果常量池中沒有字符串對象"GY",則先在常量池中創(chuàng)建"GY",再在堆中生成一個String對象,共兩個。 二: String s1=new String("GY")+new String("HAPPY");//生成三個對象,兩個在常量池,一個在JVM堆中 System.out.println(s1.intern()==s1);//true


String s1=new String("GY")+new String("HAPPY)并沒有在運行時常量池中生成“GYHAPPY"對象,調(diào)用s1.intern()時,發(fā)現(xiàn)常量池中沒有,則將對象的引用加入到池中,返回該引用(即s1地址)。 三: 詭異現(xiàn)象: String s1=new String("1")+new String("1"); System.out.println(s1.intern()==s1);//false
String s1=new String("ja")+new String("va"); System.out.println(s1.intern()==s1);//false
這是因為JVM加載過程中已經(jīng)在常量池中生成了"11","java"這些對象,因此intern函數(shù)返回的是常量池的地址。 底層實現(xiàn):1.JAVA調(diào)用C++實現(xiàn)的StringTable的intern方法,原理與JAVA中的HashMap差不多,都是用鏈表法解決Hash沖突。jdk1.6以前StringTable長度固定為1009,如果常量池中String很多,則鏈表很長,導(dǎo)致查找效率低。jdk1.7的StringTable長度可設(shè)置,-XX:StringTableSize=XXXXXX。 2.一旦常量池中的字符串達到的一定的規(guī)模后,性能會急劇下降。
|