1, String s="a"+"b"+"c"+"d"創建了幾個對象(假設之前串池是空的)
2,StringBuilder sb = new StringBuilder();
String a = "a";
String b = "b";
String c = "c";
String d = "d";
String s = a+b+c+d; 這句話創建了幾個對象
StringBuilder sb = new StringBuilder();
sb.append("a").append("b").append("c").append("d");這句話創建了幾個對象
-------------------------------------------------------------------------------------------
答案是 7 3 0
第一題:“a”“b”“c”“d” “ab”“abc”“abcd”
第二題: “ab”“abc”“abcd”
第三題:因為a”“b”“c”“d”在串池中已經存在,不會創建對象,並且StringBuilder添加字符串的時候跟String
是不一樣的,StringBuilder是不會創建對象的(所以說我們在增加字符串長度的時候盡量用StringBuilder,這樣會少創建對象,節省資源,提高效率)
所以是0個對象
第一題中如果無(假設之前串池是空的)這句,結果則為一個對象
在JVM中有一個字符串池,它用來保存很多可以被共享的String對象,這樣如果我們在使用同樣字面字符串時,它就使用字符串池中同字面的字符串。常量池是在編譯期被確定,並被保存在已編譯的.class文件中的一些數據。它包括了關於類、方法、接口等中的常量,也包括字符串常量。由於常量字符串是在編譯的時候就也被確定的,因"a"、"b"、"c"和"d"都是常量,因此變量s1的值在編譯時就可以確定。這行代碼編譯后的與String s1="abcd";是一樣的。
下面說說用+連接字符串時的情況
public class TestString { private static String str = "abc"; public static void main(String[] args) { String str1 = "a"; String str2 = "bc"; String combo = str1 + str2; System.out.println(str == combo); System.out.println(str == combo.intern()); } }
這個例子用來說明用+連接字符串時,實際上是在堆內容創建對象,那么combo指向的是堆內存存儲”abc”字符串的空間首地址,顯然str==combo是錯誤的,而str==combo.intern()是正確的,在String池中也存在”abc”,那就直接返回了,而str也是指向String池中的”abc”對象的。此例說明任何重新修改String都是重新分配內存空間,這就使得String對象之間互不干擾。也就是String中的內容一旦生成不可改變,直至生成新的對象
同時問題也來了,使用+連接字符串每次都生成新的對象,而且是在堆內存上進行,而堆內存速度比較慢(相對而言),那么再大量連接字符串時直接+是不可取的,當然需要一種效率高的方法。Java提供的StringBuffer和StringBuilder就是解決這個問題的。區別是前者是線程安全的而后者是非線程安全的,StringBuilder在JDK1.5之后才有。不保證安全的StringBuilder有比StringBuffer更高的效率
自JDK1.5之后,Java虛擬機執行字符串的+操作時,內部實現也是StringBuilder,之前采用StringBuffer實現。
總結:引用在棧而對象在堆