字串常量池與intern方法

來源:互聯網
上載者:User

看了幾篇關於intern方法的文章,總結如下:

一、主要知識點:

1、使用引號聲明的字串常量都會直接在字串常量池中產生

2、intern方法在jdk1.6與jdk1.7中有點區別,主要原因是jdk1.7中將常量池移到了堆中

3、使用intern方法會很大程度的節省記憶體


二、Java中字串建立的兩種方式:

Java中字串對象建立有兩種形式,

一種為字面量形式,如String str=" hello",

另一種就是使用標準的構造對象的方法,如String str=new String("hello");

這兩種經常使用,在記憶體上面有一些區別。這一切都是JVM為了減少字串對象重複建立,其維護了一個特殊的記憶體,這段記憶體就是字串常量池


工作原理

當代碼中出現字面量形式建立字串對象時嗎,JVM就會首先對這個字面量進行檢查,,如果字串常量池中存在相同內容的字串對象的引用,則將這個引用返回,否則新的字串對象就被建立,然後將這個引用放入字串常量池中,並返回該引用。

String str1="hello"

JVM檢測這個字面量,這裡我們認為沒有內容為"hello"的對象存在。JVM通過字串常量池尋找不到內容為"hello"的字串對象存在,那麼會建立這個字串對象,然後將剛建立的對象的引用放入到字串常量池中,並且將引用返回給變數str1。


String str2="hello"

同樣JVM還是要檢測這個字面量,JVM通過尋找字串常量池,發現內容為”droid”字串對象存在,於是將已經存在的字串對象的引用返回給變數str2。注意這裡不會重新建立新的字串對象。

驗證是否為str1和str2是否指向同一對象,我們可以通過這段代碼 System.out.println(str1 == str2);

結果為true。


String str3 = new String("hello");

當我們使用了new來構造字串對象的時候,不管字串常量池中有沒有相同內容的對象的引用,新的字串對象都會建立。因此我們使用下面代碼測試一下,

String str3 = new String("hello");
System.out.println(str1 == str3);

結果如我們所想,為false,表明這兩個變數指向的為不同的對象。


三、JDK1.6與JDK1.7中intern方法的區別:

1、JDK1.6中

在JDK1.6中,常量池是放在Perm區(屬於方法區)中的,這是和堆區完全分開的。

在JDK1.6中,intern()方法的作用:

檢查字串池裡是否存在"hello"這麼一個字串,如果存在,就返回池裡的字串;如果不存在,該方法會把"hello"添加到字串池中,然後再返回它的引用。

(1)

public static void main(String[] args) {//在常量池中添加字串helloString s1="hello";//由於常量池中已經存在"hello",所以返回該字串String s2=s1.intern();System.out.println(s2);       //hello//s1和s2都指向常量池中"hello"System.out.println(s2==s1);   //true}


(2)

public static void main(String[] args) {//在堆中建立字串並且在常量池中添加字串hello  因為使用引號聲明的字串常量都會直接在字串常量池中產生String s1=new String("hello");//由於常量池中已經存在"hello",所以返回該字串String s2=s1.intern();System.out.println(s2);       //hello//由於s1指向的字串在堆中,而s2指向的字串在常量池中,所以地址不同(==判斷的是地址)System.out.println(s2==s1);   //false}

(3)

public static void main(String[] args) {//在堆中建立字串"hello world"  在常量池中分別建立"hello"與"world"String s1=new String("hello")+new String("World");//由於常量池中不存在"hello world",所以添加該字串,並返回引用String s2=s1.intern();System.out.println(s2);       //helloWorld//由於s1指向的字串在堆中,而s2指向的字串在常量池中,所以地址不同(==判斷的是地址)System.out.println(s2==s1);   //false}

注意:在jdk1.7中會輸出true,下面將介紹。


2、在JDK1.7中

在JDK1.7中,將常量池放到了堆中。

正常情況下,使用new建立的字串對象的引用不會放入字串常量池,但是在使用JDK1.7的情況下,如果想將這個對象的引用加入到字串常量池,可以使用intern方法。調用intern後,首先檢查字串常量池中是否有該對象的引用,如果存在,則將這個引用返回給變數,否則將引用加入並返回給變數。


public static void main(String[] args) {//在堆中建立字串"hello world"  在常量池中分別建立"hello"與"world"String s1=new String("hello")+new String("World");/* * 由於常量池中不存在"hello world",但是在堆中有該字串, * 所以將引用s1返回,即s2也指向堆中的字串 */String s2=s1.intern();System.out.println(s2);       //helloWorld//所以地址相同System.out.println(s2==s1);   //trueString s3="helloWorld";//常量池中已經存在"helloWorld"的引用,所以s3也直接指向堆中的字串System.out.println(s3==s1);  //true}


關於intern()方法為什麼能夠節省記憶體,參見 Java技術——你真的瞭解String類的intern()方法嗎

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.