有一道題目是這樣的:
new String("aaa")建立了幾個物件?答案是創建一個或2個,理由是如果常數區中存在了aaa變量,則只在堆中創建一個;如果常量區不存在aaa變量,則分別在常量區和堆中各創建一個。
但我實際測試的結果卻不符:
String s1 = new String("aaa");
String s2 = "aaa";
System.out.println(s1 == s2); //false
如果說new String("aaa")在堆中和常數區中都創建了對象,那麼為什麼s2不直接復用s1的常數池的引用呢?
補充:
發現自己想錯了,s1應該指向的堆中的元素,而s2指向的是常數池中的,所以兩者不相等是對的,那有沒有辦法測試測試出new String("aaa")也同時在常數池中建立物件了呢?
又或String s3 = "aa".concat("a"); 請問這個s3是指向堆中還是指向常數池的,它能否復用常數池中的變數呢?
當一個String實例呼叫intern()方法時,會查找常數池中是否有相同的字串常數,如果有,則傳回其的引用,如果沒有,則在常數池中增加一個等於str的字串並傳回它的引用,由於s2已經在常數池中,所以s1.intern()不會再創建,而是直接引用同一個"aaa"。
如果這樣還不夠明顯,那我們就來試驗,
然後命令列
注意常量池有 VV
問題一:
String a = “aaa”,會在常數池中建立對象,如果常數池中存在同樣的對象,那a就直接指向該對象。而 String a = new String("aaa"),若常數池中存在,則不在常數池中創建,只在堆中創建。
問題二:
從原始碼找出答案String s3 = "aa".concat("a"); 其實相當於 String s3 = new String("aaa"),會在堆中建立物件。
String不是每次賦值都會重新建立一個String物件實例嗎?所以才會有StringBuilder呀。
按照物件導向的思想,有沒有同時在常數池創建對象,可能String自己最清楚,嗯,他有一個intern()方法。
前面幾位的回答已經非常好了,我補充一句,我們常說的「把字串放到常數池」是指把字串的引用放到字串常數池(String Pool,本質是一個哈希表)中,字串本身還是放在堆上的。
雷雷