6

重複の可能性:
Javaの文字列プールに関する質問

javaStringsオブジェクトの作成に疑問があります。

String s1 = "Hello"+"world";
String s2 = s1+"Java";

このプログラムでは、作成されるStringオブジェクトの数とその方法を説明してください。ありがとう。

4

7 に答える 7

5

答えは3です

JVMの開始ごとに2つのStringオブジェクトが1回作成されます。

  • "こんにちは世界"
  • 「Java」

どちらも定数(コンパイル時に認識される)であるため、インターンされます。

これらは、このコードが実行されるたびに再利用されます。上記の2つの文字列を連結するためにStringBuilderが作成されます。それらへの参照はs1とs2に割り当てられます。

コードのバイトコードは次のとおりです。

   0:   ldc #37; //String Helloworld
   2:   astore_1
   3:   new #39; //class java/lang/StringBuilder
   6:   dup
   7:   aload_1
   8:   invokestatic    #41; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   11:  invokespecial   #47; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   14:  ldc #50; //String Java
   16:  invokevirtual   #52; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   19:  invokevirtual   #56; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   22:  astore_2
   23:  return
于 2013-01-07T04:22:02.177 に答える
5

StringJVM の実装が異なるため、いくつかの違いがあるため、作成される の数を正確に言うことはできません。

不変クラスであるため、 String素朴な答えは5です。StringBufferStringBuilderString

連結は -calls を介して要約されappend()ます。

編集:ここでいくつかの異なる答えがあるので、私が5と言った理由を説明します:

  1. "こんにちは"
  2. "世界"
  3. (s1)「ハローワールド」
  4. 「ジャバ」
  5. (s2)「ハローワールドJava」
于 2013-01-07T04:23:57.960 に答える
2

コンパイルされたコードを見ると、次のことが簡単に推測できます。

String s1 = "Helloworld";
String s2 = (new StringBuilder(String.valueOf(s1))).append("Java").toString();

実行前にコンパイラによって多くの最適化が行われるため、ソース コードを見ただけでは正確に知ることはできません。

ここでは、s1 用に 1 つの String オブジェクトが作成され、s2 用に別の String オブジェクトが作成されていることがわかります。ここでは、文字列プールに「Helloworld」と「Java」の 2 つの文字列リテラルがあります。

于 2013-01-07T04:27:41.813 に答える
1

Program.class を逆コンパイルすると、実際のコードが表示されます

String s1 = "Helloworld";
String s2 = (new StringBuilder(String.valueOf(s1))).append("Java").toString();

10個のオブジェクトのようです。各文字列内にはchar[] value、これが別のオブジェクト+ StringBuilder内の別のchar []であるためです

于 2013-01-07T04:27:04.553 に答える
0

答えは 3 です。

逆アセンブルされた結果は、次の方法で表示できます。

javap -verbose YourClass

定数プールには次が含まれます。

...
const #17 = Asciz       Helloworld;
...
const #30 = Asciz       Java;
...

これは、2 つの文字列 ("Helloworld" と "Java") が、定数プールに自動的にインターンされるコンパイル時の定数式であることを意味します。

コード:

Code:
 Stack=3, Locals=3, Args_size=1
 0:   ldc     #16; //String Helloworld
 2:   astore_1
 3:   new     #18; //class java/lang/StringBuilder
 6:   dup
 7:   aload_1
 8:   invokestatic    #20; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
 11:  invokespecial   #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
 14:  ldc     #29; //String Java
 16:  invokevirtual   #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 19:  invokevirtual   #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
 22:  astore_2
 23:  return

これは、s2 が StringBuilder.append() および toString() によって作成されたことを示します。

これをさらに興味深いものにするために、javac は定数折りたたみでコードを最適化できます。次のコードで作成された文字列の数を推測できます。

final String s1 = "Hello" + "world";
String s2 = s1 + "Java";

「最終」は、s1 が定数であることを意味し、javac が s2 およびインターン s2 の値を構築するのに役立ちます。したがって、ここで作成される文字列の数は 2 です。

于 2013-01-07T07:36:07.250 に答える
-1

はい、5 つの String オブジェクトが作成されます。文字列は不変です。手順は次のとおりです。1. 最初に「Hello」 2. 次に別のオブジェクト「Hello World」 3. 次に別のオブジェクト「Java」 4. 次に s1+「Java」、最後に s2 が作成されます。

于 2013-01-07T04:34:07.483 に答える
-2

実際には、2 つの String リテラルだけで String オブジェクトは作成されません。あなたが持っているように文字列が初期化されるとき、それらはオブジェクトではなくリテラルです。String オブジェクトを作成する場合は、次のようにします。

String a = new String("abcd");
于 2013-01-07T04:24:44.090 に答える