3

Javaの文字列の不変性については多く質問があり、質問の作成者が実際に参照を再割り当てします。

ただし、文字列の再割り当てがないように見えるという注目すべきケースがあります。

String s = "hello";
s += " world";

これは、文字列の実際の変更として表示されます。自宅でお試しください。

これはある種の構文糖衣であり、コンパイラによって次と同じセマンティクスを持つものに変換されると確信しています。

String s = "hello";
s = s + " world";

誰かがこの事実を確認できますか?

4

4 に答える 4

5

間違い。

x += yの省略形ですx = x + y
これは引き続き通常の割り当て操作であり、既存のインスタンスを変更することはありません。

于 2012-12-10T20:29:23.010 に答える
4

私はそれを確認も否定もできません。最適化コンパイラーが、他のスレッドがsの初期(pre-)値を「見る」ことができないことを証明できれば+=、連結を最適化して、コードを同等のものにコンパイルすることができます。

String s = "hello world";

コンパイラは、メモリモデルに準拠している限り、ソースからバイトコードに正確に変換する方法に関して大きな自由を持っています。

于 2012-12-10T20:36:07.860 に答える
4

これは新しいオブジェクトであり、元のオブジェクトは変更されません。

これ:

public static void main(String[] args) {

    String s = "hello";
    s += " world";
    System.out.println(s);

}

これに翻訳してください:

public static void main(java.lang.String[]);
    Code:
        0: ldc           #2                  // String hello
        2: astore_1
        3: new           #3                  // class java/lang/StringBuilder
        6: dup
        7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        10: aload_1
        11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        14: ldc           #6                  // String  world
        16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        22: astore_1
        23: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
        26: aload_1
        27: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        30: return
}

これにより、2つのが作成され、それらが新しいオブジェクトStringに追加されます。String

于 2012-12-10T20:47:00.613 に答える
0

次のソースコードを前提として、Javaバイトコードを読み取れない人のためにskynorthの答えを拡張するには:

public static void main(String... args) {
    String s = "hello";
    s += "world";
}

コンパイルされたクラスファイルでJADデコンパイラを実行すると、次のJavaコードが取得されます。

public static void main(String args[]) {
    String s = "hello";
    s = (new StringBuilder(String.valueOf(s))).append("world").toString();
}

これは非常に自明であり、skynortが投稿したバイトコードに正確に対応しています。

于 2012-12-10T20:59:38.800 に答える