String池化及intern方法的作用

String池化

String池 :String是不可改變的,爲了提高效率Java引用了字符串池的概念,例如new String(“abc”);首先會在String池中創建一個對象“abc”,因爲有NEW的存在所以會分配地址空間copy String池的內容。當出現的String對象在String池中不存在時即在String池中創建該對象。

字符串對象的創建方式有兩種如下:

String s1 = new String("");//第一種不會入池

String s2 = "";//第二種看情況而定(等號右邊如果是常量則入池,非常量則不入池)

例:

String s3 = "a" + "b"; //"a"是常量,"b"是常量,常量+常量=常量,所以會入池.

String s4 = s1 + "b";   //s1是變量,"b"是常量,變量+常量!=常量,所以不會入池.

一旦入池的話,就會先查找池中有無此對象.如果有此對象,則讓對象引用指向此對象;如果無此對象,則先創建此對象,再讓對象引用指向此對象.

intern()

存在於.class文件中的常量池,在運行期被JVM裝載,並且可以擴充。String的intern()方法就是擴充常量池的一個方法;當一個String實例str調用intern()方法時,Java查找常量池中是否有相同Unicode的字符串常量,如果有,則返回其的引用,如果沒有,則在常量池中增加一個Unicode等於str的字符串並返回它的引用;

例3:

String s0= “kvill”;  
String s1=new String(”kvill”);  
String s2=new String(“kvill”);  
System.out.println( s0==s1 );  
System.out.println( “**********” );  
s1.intern();  
s2=s2.intern(); //把常量池中“kvill”的引用賦給s2  
System.out.println( s0==s1);  
System.out.println( s0==s1.intern() );  
System.out.println( s0==s2 );  

結果爲:

false  
**********  
false //雖然執行了s1.intern(),但它的返回值沒有賦給s1  
true //說明s1.intern()返回的是常量池中”kvill”的引用  
true  

最後我再破除一個錯誤的理解:

有人說,”使用String.intern()方法則可以將一個String類的保存到一個全局String表中,如果具有相同值的Unicode字符串已經在這個表中,那麼該方法返回表中已有字符串的地址,如果在表中沒有相同值的字符串,則將自己的地址註冊到表中”。如果我把他說的這個全局的String表理解爲常量池的話,他的最後一句話,“如果在表中沒有相同值的字符串,則將自己的地址註冊到表中”是錯的:

看例4:

String s1=new String("kvill");  
String s2=s1.intern();  
System.out.println( s1==s1.intern() );  
System.out.println( s1+" "+s2 );  
System.out.println( s2==s1.intern() );  

結果:

false 
kvill kvill  
true  

在這個類中我們沒有聲名一個”kvill”常量,所以常量池中一開始是沒有”kvill”的,當我們調用s1.intern()後就在常量池中新添加了一個”kvill”常量,原來的不在常量池中的”kvill”仍然存在,也就不是“將自己的地址註冊到常量池中”了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章