検索

ホームページ  >  に質問  >  本文

java - 以下创建了几个对象

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中文网2885日前871

全員に返信(3)返信します

  • 高洛峰

    高洛峰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 配列を使用して文字列を保存します。配列の容量が足りない場合は、デフォルトのサイズが拡張されます。 16 + "abc" 長さ = 19、"abc567" の長さは 6、3 + 3 < 19 であるため、拡張は発生しません。
    • もう 1 つのポイントは、StringBuffer と StringBuilder が AbstractStringBuilder を継承するため、親クラスが作成される可能性があることです。
    • これは逆コンパイルされたコードです:
    リーリー

    返事
    0
  • 迷茫

    迷茫2017-04-18 10:25:06

    先に私の答えを言わせてください:私はそれが 3 だと思います。


    まず、create object の具体的な意味を明確にしましょう。私の理解によれば、文字列が character constant である場合、文字列オブジェクトはコンパイル時に決定されます。定数プールに格納されるため、 String b = new String("abc") のような操作がある場合は、文字列オブジェクトの作成としてカウントされません。文字列オブジェクトを作成すると、文字列オブジェクトが取得され、変数 b に関連付けられます。创建对象 的具体含义. 按我的理解, 如果字符串是 字符常量, 那么这个字符串对象是在编译时候确定好的, 它是存放在常量池中的, 因此就不算是创建了一个字符串对象, 而如果有 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")

      上記の定義によれば、「a」、「b」、「abc」、「567」はすべて定数であり、定数プールに配置されるため、オブジェクトとして作成されません。
    コードを見てみましょう:
    ソースコード:

    リーリー

    便宜上、各行に手動で番号を付けました。
    対応するバイトコードを見てみましょう:🎜 リーリー 🎜バイトコードからわかるように、ソース コード a = a+b の 4 行目は次のコードに変換されます。 リーリー 🎜次に、ここで新しいオブジェクト new StringBuilder() が作成され、builder.toString() メソッドが呼び出されます。そのソース コードは次のとおりです。 リーリー 🎜そのため、builder.toString() メソッドは String オブジェクトを作成するため、2 つのオブジェクト が作成されました。🎜 🎜次に、5 行目 StringBuffer d = new StringBuffer("abc") は間違いなくオブジェクト StringBuffer を作成するため、3 つのオブジェクト が存在します。 StringBuffer d は最初から最後まで toString メソッドを呼び出すわけではないので、冗長な String は作成されないことに注意してください。🎜 🎜 🎜概要:🎜
    • 🎜"a": 文字列定数。作成されたオブジェクトとしてカウントされません🎜🎜
    • 🎜"b": 文字列定数。作成されたオブジェクトとしてカウントされません🎜🎜
    • 🎜builder オブジェクト: a = a+b の実行時に作成されます。🎜🎜
    • 🎜"ab": StringBuilder.toString() によって作成されました。🎜🎜
    • 🎜"abc": 文字列定数。作成されたオブジェクトとしてカウントされません🎜🎜
    • 🎜"567": 文字列定数、作成されたオブジェクトはカウントされません🎜🎜
    • 🎜d: new StringBuffer("abc") によって作成されました。🎜🎜 🎜 🎜最終的に 3 つのオブジェクトが作成されます。🎜

      返事
      0
  • 阿神

    阿神2017-04-18 10:25:06

    ご回答ありがとうございます。残念ながら、今は逆コンパイルされたコードを理解できません。

    返事
    0
  • キャンセル返事