JDK1.8字符串常量池里存的是String對象還是引用?


  眾所周知,JDK1.8版本中,String常量池已經從方法區中的運行時常量池分離到堆中了,那么在堆中的String常量池里存的是String對象還是引用呢?直接查看API:

img

  翻譯:String類的intern()方法:一個初始為空的字符串池,它由類String獨自維護。當調用 intern方法時,如果池已經包含一個等於此String對象的字符串(用equals(oject)方法確定),則返回池中的字符串。否則,將此String對象添加到池中,並返回此String對象(注意是常量池中的對象,不是堆中的對象)的引用。 對於任意兩個字符串s和t,當且僅當s.equals(t)為true時,s.intern() == t.intern()才為true。所有字面值字符串和字符串賦值常量表達式都使用 intern方法進行操作。

總結

  JDK1.8版本的字符串常量池中存的是字符串對象,以及字符串常量值。

  附上常考面試題:

  1. 輸出結果?創建了幾個對象?
String s1 = "abc";
String s2 = "abc";
System.out.println(s1==s2);

  結果輸出:

true

  創建了1個對象。采用字面值的方式創建一個字符串時,JVM首先會去字符串池中查找是否存在"abc"這個對象,如果不存在,則在字符串池中創建"abc"這個對象,然后將池中"abc"這個對象的引用地址返回給"abc"對象的引用s1,這樣s1會指向池中"abc"這個字符串對象;如果存在,則不創建任何對象,直接將池中"abc"這個對象的地址返回,賦給引用s2。因為s1、s2都是指向同一個字符串池中的"abc"對象,所以結果為true。

  1. 輸出結果?創建了幾個對象?
String s3 = new String("xyz");
String s4 = new String("xyz");
System.out.println(s3==s4);

  結果輸出:

false

  創建了3個對象。采用new關鍵字新建一個字符串對象時,JVM首先在字符串池中查找有沒有"xyz"這個字符串對象,如果有,則不在池中再去創建"xyz"這個對象了,直接在堆中創建一個"xyz"字符串對象,然后將堆中的這個"xyz"對象的地址返回賦給引用s3,這樣,s3就指向了堆中創建的這個"xyz"字符串對象;如果沒有,則首先在字符串池中創建一個"xyz"字符串對象,然后再在堆中創建一個"xyz"字符串對象,然后將堆中這個"xyz"字符串對象的地址返回賦給s3引用,這樣,s3指向了堆中創建的這個"xyz"字符串對象。s4則指向了堆中創建的另一個"xyz"字符串對象。s3 、s4是兩個指向不同對象的引用,結果當然是false。

  1. 代碼詳解
String s1 = new StringBuilder().append("ja").append("va1").toString();
System.out.println(s1.intern() == s1);

  輸出結果:

true

  詳解:StringBuilder().toString()這個方法雖然是new了一個String對象,但其實和"java1"是一樣的,大家可以看下源碼,這里的s1.intern()返回的是常量池中字符串的引用,所以s1.intern() == s1


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM