String a,b,c;
a = "a";
b = "b";
a = a+b;
StringBuffer d = new StringBuffer("abc");
d = d.append("567");
我觉得是6个,"a" "b" "ab" "abc" "567" 还有d.
高洛峰2017-04-18 10:25:06
說下我的理解,歡迎拍磚
a = "a"; 編譯時字串"a"放入常數池,不會在堆上建立物件
b = "b"; 同理
a = a + b;new 一個StringBuilder對象,append(a), append(b), 最後返回tostring()給a.
StringBuffer d = new StringBuffer("abc"); 這裡肯定建立一個對象,同時"abc"進入常數池
d = d.append("567"); StringBuffer 使用一個char數組保存字串,append會往數組裡面加入"567",如果數組容量不夠,會進行擴充,預設大小是16 + "abc"的長度= 19,"abc567"長度為6, 3 + 3 < 19所以不會造成擴容。
還有一點,StringBuffer 和 StringBuilder是繼承了AbstractStringBuilder的,可能會造成父類別的建立。
這是反編譯出來的程式碼:
/**
*
* 源代码
*public class TestString {
* public static void main(String args[]) {
* String a = "a";
* String b = "b";
* String c = a + b;
* }
*}
*
*/
Compiled from "TestString.java"
public class TestString {
public TestString();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String a
2: astore_1
3: ldc #3 // String b
5: astore_2
6: new #4 // class java/lang/StringBuilder
9: dup
10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
13: aload_1
14: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_2
18: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_3
25: return
}
迷茫2017-04-18 10:25:06
先說一下我的答案: 我感覺是 3 個.
首先, 明確一下 创建对象
的具体含义. 按我的理解, 如果字符串是 字符常量
, 那么这个字符串对象是在编译时候确定好的, 它是存放在常量池中的, 因此就不算是创建了一个字符串对象, 而如果有 String b = new String("abc")
之类的操作, 那么可以认为是创建了字符串对象, 并与变量 b
關聯.
根據上面的定義, 那麼有: "a", "b", "abc", "567" 都是常數, 放在常量池中的, 因此就不算是創建對象了.
那麼來看一下程式碼:
原始碼:
1: String a,b,c;
2: a = "a";
3: b = "b";
4: a = a+b;
5: StringBuffer d = new StringBuffer("abc");
6: d = d.append("567");
為了方便起見, 我手動給每一行編號了.
再來看一下對應的字節碼:
Code:
stack=3, locals=5, args_size=1
0: ldc #2 // String a
2: astore_1
3: ldc #3 // String b
5: astore_2
6: new #4 // class java/lang/StringBuilder
9: dup
10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
13: aload_1
14: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_2
18: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_1
25: new #8 // class java/lang/StringBuffer
28: dup
29: ldc #9 // String abc
31: invokespecial #10 // Method java/lang/StringBuffer."<init>":(Ljava/lang/String;)V
34: astore 4
36: aload 4
38: ldc #11 // String 567
40: invokevirtual #12 // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
43: astore 4
45: return
由字節碼可以看出, 源碼的第四行 a = a+b
翻譯為如下程式碼:
StringBuilder builder = new StringBuilder();
builder.append(a);
builder.append(b);
a = builder.toString();
那麼這裡就新建了一個物件 new StringBuilder()
, 接着调用 builder.toString()
方法, 它原始碼如下:
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
於是 builder.toString()
方法创建了一个 String 对象, 因此目前我们已经创建了 两个对象
了.
接著第五行 StringBuffer d = new StringBuffer("abc")
毫无疑问是 创建了对象 StringBuffer
, 于是我们就有 三个对象
了. 有一点需要注意的是 StringBuffer d
从始至终都没有调用 toString
方法, 因此就不會有多餘的 String 創建出來.
總結:
"a": 字串常數, 不算創建物件
"b": 字串常數, 不算創建物件
builder 物件: 在執行 a = a+b
時建立.
"ab": 由 StringBuilder.toString()
創建.
"abc": 字串常數, 不算創建物件
"567": 字串常數, 不算創建物件
d: 透過 new StringBuffer("abc")
創建.
因此最終有三個物件創建了.