字元串常量池的深度了解
-
- 場景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