常見的面試題,下面程式碼中建立了幾個物件
new String("yefeng");
為了明白這個問題,我們從底層原理來分析
String name = "yefeng"; // 在常量池中
String name1 = new String("yefeng"); // 在堆上
當我們如果直接賦值的話,字串"yefeng"會唄儲存在常量池中,只有一份,此時的賦值操作是建立0個或者1個物件。
如果常量池中已經存在了"yefeng", 那麼不會再建立物件,直接引用賦值給name,如果常量池中沒有"yefeng",那麼建立一個物件,並引用賦值給name。
如果透過new String("yefeng");的形式會是怎麼樣的?
當JVM遇到上述程式碼,會檢索常量池中是否存在'yefeng",如果不存在,則會先在常量池中建立一個這樣的字串。再透過new操作,會在堆中建立一個儲存"yefeng"的String物件,物件然後在賦值給name1。此過程會建立2個物件。
當然,如果檢索常量池時發現已經存在了對應的字串,那麼只會在堆內建立一個新的String物件,此過程只建立
了1個物件。在上述過程中檢查常量池是否有相同Unicode的字串常量時,使用的方法便是String中的intern()方法。
public native String intern();
上面的示意圖我們可以看到在堆內建立的String物件的char value[]屬性指向了常量池中的char value[]。還是上面
的示例,如果我們透過debug模式也能夠看到String的char value[]的引用地址。
圖中兩個String物件的value值的引用均為{byte[6]@1181},也就是說,雖然是兩個物件,但它們的value值均指向常量池中的同一個地址。當然,大家還可以拿一個複雜物件(Person)的字串屬性(name)相同時的debug結果進行比對,結果是一樣的。