java的string存放位置的疑惑
仅有的幸福
仅有的幸福 2017-05-17 10:00:54
0
6
702

有一道題目是這樣的:

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是指向堆中還是指向常數池的,它能否復用常數池中的變數呢?

仅有的幸福
仅有的幸福

全部回覆(6)
过去多啦不再A梦
    String s1 = new String("aaa");
    String s2 = "aaa";
    System.out.println(s1 == s2); //false
    System.out.println(s1.intern() == s2); //true

當一個String實例呼叫intern()方法時,會查找常數池中是否有相同的字串常數,如果有,則傳回其的引用,如果沒有,則在常數池中增加一個等於str的字串並傳回它的引用,由於s2已經在常數池中,所以s1.intern()不會再創建,而是直接引用同一個"aaa"。

如果這樣還不夠明顯,那我們就來試驗,

public class Cons {
    public static void main(String[] args) throws InterruptedException {
        String s1 = new String("vv");
    }
}

然後命令列

注意常量池有 VV

PHPzhong

問題一:

String a = “aaa”,會在常數池中建立對象,如果常數池中存在同樣的對象,那a就直接指向該對象。而 String a = new String("aaa"),若常數池中存在,則不在常數池中創建,只在堆中創建。

String a = new String("aaa");
String b = new String("aaa");
System.out.println(a == b);//比较两者堆中的引用返回false
System.out.println(a.intern() == b.intern());//比较两者常量池中的引用,返回true

問題二:

從原始碼找出答案String s3 = "aa".concat("a"); 其實相當於 String s3 = new String("aaa"),會在堆中建立物件。

public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = Arrays.copyOf(value, len + otherLen);
    str.getChars(buf, len);
    return new String(buf, true);
}

伊谢尔伦

String不是每次賦值都會重新建立一個String物件實例嗎?所以才會有StringBuilder呀。

左手右手慢动作

按照物件導向的思想,有沒有同時在常數池創建對象,可能String自己最清楚,嗯,他有一個intern()方法。

漂亮男人

前面幾位的回答已經非常好了,我補充一句,我們常說的「把字串放到常數池」是指把字串的引用放到字串常數池(String Pool,本質是一個哈希表)中,字串本身還是放在堆上的。

过去多啦不再A梦

雷雷

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板