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


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


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