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

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 配列を使用して文字列を保存します。配列の容量が足りない場合は、デフォルトのサイズが拡張されます。 16 + "abc" 長さ = 19、"abc567" の長さは 6、3 + 3

    もう 1 つのポイントは、StringBuffer と StringBuilder が AbstractStringBuilder を継承するため、親クラスが作成される可能性があることです。
  • これは逆コンパイルされたコードです:
リーリー
いいねを押す +0
迷茫

先に私の答えを言わせてください:私はそれが 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
阿神

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

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート