7

作成されるStringオブジェクトの数

私はSCJPのために勉強していますが、この文字列の問題に頭を悩ませることはできないようです。質問の見方によっては、いくつかの答えが考えられるようです。

次の初期化では、いくつの文字列オブジェクトが作成されますか?

String s1 = "A" + "B" + "C" + "D";
System.out.println(s1)

最初は5つのオブジェクトを考えました。

"A"
"B"
"C"
"D"
"ABCD"

しかし、それについて考えると、たとえばコンパイラ"A" + "B"が1つのオブジェクトとして連結されるため、よくわかりません。つまり、7つのオブジェクトを作成しますか?

"A"
"B"
"C"
"D"
"AB"
"ABC"
"ABCD" 

また、コードが次のように変更された場合に作成されるオブジェクトの数

String s1 = new String("A" + "B" + "C" + "D");
System.out.println(s1);

そして最後にどうですか:

String s1 = "A";
String s2 = new String("A");

上記の例では、2つのオブジェクトのみが作成されると思います

object 1 - "A"
object 2 - a String object that refers to the "A" object above.

これは正しいですか、それとも関連していませんか?つまり、定数プールから参照されるオブジェクトは、s2参照によって参照されるオブジェクトとは異なります。

ありがとう

編集

また、最終的に定数プールに入れられるオブジェクトだけでなく、破棄されるオブジェクトも含めて、作成されたオブジェクトの総数を知りたいことに注意してください。

編集

ジョンの答えを見ると、オブジェクトの作成方法を完全に誤解している可能性があります。文字列は定数プールで1回だけ作成され、再利用されることは知っていますが、「final」文字列が作成されるときに実行されるプロセスがわかりません。これが私が読んでいる本のセクションで、ここでの答えとは正反対の一時的なオブジェクトが作成されることを示唆しているようです。(または、本が間違っているか、私が本を誤解している可能性があります)

コードサンプルは

String s1 = "spring ";  
String s2 = s1 + "summer ";  
s1.concat("fall ");  
s2.concat(s1);  
s1 += "winter";  
System.out.println(s1 + " " + s2);

質問は

出力は何ですか?追加のクレジットとして、printlnステートメントの前に作成されたStringオブジェクトの数と参照変数の数。

そして答えは

このコードフラグメントの結果はですspring water spring summer。s1とs2の2つの参照変数があります。「春」、「夏」(失われた)、「春夏」、「滝」(失われた)、「春秋」(失われた)、「春夏春」(失われた)の合計8つのStringオブジェクトが作成されました。 、"winter"(失われた)、 "spring winter"(この時点で "spring"は失われます)。このプロセスで失われないのは、8つのStringオブジェクトのうち2つだけです。

ありがとう

4

3 に答える 3

13

コンパイラは、「A」+「B」+「C」+「D」全体を単一の定数に連結します。したがって、最初の例では、単一の文字列のみが作成されます。同じコードを複数回実行すると、同じ文字列が再利用されます。定数はクラスファイルに配置され、クラスがロードされると、VMは等しい文字列がすでに文字列プールにあるかどうかをチェックします。したがって、複数のクラスに同じコードがある場合でも、VMはそれを再利用します。

次のコマンドを使用して、クラス内の定数プールに1つの文字列のみが含まれていることを確認できますjavap

javap -v Test

Constant pool:
   #1 = Methodref   #6.#17     //  java/lang/Object."<init>":()V
   #2 = String      #18        //  ABCD
   #3 = Fieldref    #19.#20    //  java/lang/System.out:Ljava/io/PrintStream;

ただし、ここでは:

String s1 = "A";
String s2 = new String("A");

最終的には2つの別々の文字列オブジェクトになります。1つ(定数)は、コードを実行するたびに再利用され(2つのステートメント間で共有され)、毎回コンストラクターが呼び出されるため、新しいものが作成されます。

したがって、たとえば、このメソッドは次のようになります。

public static void foo() {
    for (int i = 0; i < 5; i++) {
        String s1 = "A";
        String s2 = new String("A");
    }
}

...最終的には6つの文字列オブジェクトを使用します。1つは定数用で、メソッドを呼び出すたびに5つの新しいオブジェクトが作成されます。

于 2011-11-29T19:44:51.557 に答える
2
String s1 = "A" + "B" + "C" + "D";

コンパイラは、文字列リテラル「ABCD」を1つだけ作成し、それを文字列プールに入れます。1つのオブジェクトが作成されます(文字列プール内のオブジェクト)。


String s1 = new String("A" + "B" + "C" + "D");

文字列リテラルからコピーしていることを除いて、ここでも同じです。したがって、ここで2つのオブジェクトが作成されます。new文字列プールに1つずつ。


String s1 = "A";
String s2 = new String("A");

ここでも同じで"A"、文字列プールの定数になります。コンストラクターがそれをコピーします。したがって、ここでは2つのオブジェクトが作成されます。

于 2011-11-29T19:44:08.753 に答える