java - 以下创建了几个对象
PHP中文网
PHP中文网 2017-04-18 10:23:06
0
3
625

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.

PHP中文网
PHP中文网

认证0级讲师

全部回覆 (3)
小葫芦

說下我的理解,歡迎拍磚

  • 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

  • 還有一點,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."":()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."":()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 }
    迷茫

    先說一下我的答案: 我感覺是 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."":()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."":(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")創建.

    因此最終有三個物件創建了.

      阿神

      謝謝各位的回答,大概理解了,可惜我現在看不懂反編譯的程式碼

        最新下載
        更多>
        網站特效
        網站源碼
        網站素材
        前端模板
        關於我們 免責聲明 Sitemap
        PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!