天天看點

字元串常量池的深度了解

字元串常量池的深度了解

    • 場景1:
    • 場景2:
    • 場景3:
    • 場景4:
    • 場景5:
    • 場景6:

場景1:

分析:有字面量1,首先會去字元串常量池中找有沒有字元串值為1的字元串對象,無,就會在字元串常量池中建立1個字元串對象,其中HashtableEntry(和字元串常量池中的每個值的對象一一對應)的key為hash值,value存的是字元串對象的位址,即instanceOopDesc位址,此時字元串對象instanceOopDesc并沒有值1,它的值1是存在堆中的一個叫typeArrayOopDesc的char數組中;接着new就會在堆中建立字元串對象,它的值也是存在typeArrayOopDesc中,兩個instanceOopDesc都維護者一個指向typeArrayOopDesc的引用。

字元串常量池的深度了解

場景2:

字元串常量池的深度了解
字元串常量池的深度了解

場景3:

字元串常量池的深度了解

場景4:

分析:

String s1= "1"+"2"

在編譯期會優化成

String s1= "12";

字元串常量池的深度了解
字元串常量池的深度了解

場景5:

分析:往深一點來說這串代碼生成了9個對象,為啥呢?第一個StringBuider,其次就是圖中8個堆中的字元串對象是StringBuider通過apend和toString方法操作後生成的

字元串常量池的深度了解
字元串常量池的深度了解

場景6:

知識補充:

  • jdk1.8:當一個字元串調用 intern() 方法時,如果 String Pool 中:
    • 存在一個字元串和該字元串值相等(使用 equals() 方法進行确定),就會傳回 String Pool 中字元串的引用(需要變量接收)
    • 不存在,會把對象的引用位址複制一份放入串池,并傳回串池中的引用位址,前提是堆記憶體有該對象。因為 Pool 在堆中,為了節省記憶體不再建立新對象
  • jdk1.6:将這個字元串對象嘗試放入串池,如果有就不放入,傳回已有的串池中的對象的位址;如果沒有會把此對象複制一份,放入串池,把串池中的對象傳回

分析:new String(“111”)+new String(“222”)一般來說會建立4個對象,s1指向堆中的值為111222的對象,jdk1.8中s.intern會在字元串常量池中找是否有值為111222的對象,這道題中沒有,然後就會在字元串常量池中建立一個HashtableEntry,value存的是堆中值為111222的對象的位址,指向它。s2="111222"回到字元串常量池中找是否有值為111222的對象,由于已經有HashtableEntry指向堆中值為111222的對象,說明字元串常量池中有,即使它不在字元串常量池中,是以s2也指向堆中的對象,為true。

字元串常量池的深度了解
字元串常量池的深度了解

思考:為什麼為false

字元串常量池的深度了解
字元串常量池的深度了解