6

JavaでStringの s とs の使用法について議論していました。StringBufferこれら 2 つの例のそれぞれで、いくつのオブジェクトが作成されますか?

例 1:

String s = "a";
s = s + "b";
s = s + "c";        

例 2:

StringBuilder sb = new StringBuilder("a");
sb.append("b");
sb.append("c");

私の意見では、例 1 では 5 個、例 2 では 4 個のオブジェクトが作成されます。

4

4 に答える 4

6

メモリ プロファイラを使用して正確なカウントを取得しました。

私のマシンでは、最初の例で 8 つのオブジェクトが作成されます。

String s = "a";
s = s + "b";
s = s + "c";
  • 型の 2 つのオブジェクトString
  • 型の 2 つのオブジェクトStringBuilder
  • タイプ の 4 つのオブジェクトchar[]

一方、2 番目の例:

StringBuffer sb = new StringBuffer("a");
sb.append("b");
sb.append("c");

2 つのオブジェクトを作成します。

  • タイプの 1 つのオブジェクトStringBuilder
  • タイプ の 1 つのオブジェクトchar[]

これはJDK 1.6u30を使用しています。

sb.toString()PS 比較を公平にするために、おそらく2 番目の例の最後で呼び出す必要があります。

于 2012-05-04T15:16:46.100 に答える
5

作成されたオブジェクトに関して:

例 1 は 8 つのオブジェクトを作成します。

String s = "a"; // No object created
s = s + "b"; // 1 StringBuilder/StringBuffer + 1 String + 2 char[] (1 for SB and 1 for String)
s = s + "c"; // 1 StringBuilder/StringBuffer + 1 String + 2 char[] (1 for SB and 1 for String)

例 2 は 2 つのオブジェクトを作成します。

StringBuffer sb = new StringBuffer("a"); // 1 StringBuffer + 1 char[] (in SB)
sb.append("b"); // 0
sb.append("c"); // 0

公平を期すために、 new char[] が実際にJavaでオブジェクトを作成したことを知りませんでした(しかし、作成されたことは知っていました)。それを指摘してくれたaixに感謝します。

于 2012-05-04T06:29:32.507 に答える
4

答えは、Java バイトコードを分析することで判断できます ( を使用javap -c)。例 1 は 2 つのStringBuilderオブジェクト (行 #4 を参照) と 2 つのStringオブジェクト (行 #7 を参照) を作成しますが、例 2 は 1 つのStringBuilderオブジェクト (行 #2 を参照) を作成します。

char[]オブジェクトも考慮する必要があることに注意してください(配列は Java のオブジェクトであるため)。オブジェクトは両方とも、基になる を使用して実装されStringます。したがって、例 1 では8 つのオブジェクトが作成され、例 2 では 2つのオブジェクトが作成されます。StringBuilderchar[]

例 1:

public static void main(java.lang.String[]);
  Code:
   0:   ldc             #2; //String a
   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 b
   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:  new             #3; //class java/lang/StringBuilder
   26:  dup
   27:  invokespecial   #4; //Method java/lang/StringBuilder."<init>":()V
   30:  aload_1
   31:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   34:  ldc             #8; //String c
   36:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   39:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   42:  astore_1
   43:  return   
}

例 2:

public static void main(java.lang.String[]);
  Code:
   0:   new             #2; //class java/lang/StringBuilder
   3:   dup
   4:   ldc             #3; //String a
   6:   invokespecial   #4; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   9:   astore_1
   10:  aload_1
   11:  ldc             #5; //String b
   13:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   16:  pop
   17:  aload_1
   18:  ldc             #7; //String c
   20:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   23:  pop
   24:  return  
}
于 2012-05-04T06:51:17.197 に答える
-1

答えは、言語の特定の実装 (コンパイラとランタイム ライブラリ) に結び付けられています。特定の最適化オプションが存在するかどうかにさえ。そしてもちろん、実装のバージョン (そして暗黙のうちに、それが準拠している JLS)。したがって、最小値と最大値の観点から話す方が適切です。実際、この演習はより良い結果をもたらします

Ex1 の場合、オブジェクトの最小数は 1 です (コンパイラは定数のみが含まれていることを認識し、 のコードのみを生成しますString s= "abc" ;)。実装に応じて、最大値は何でもかまいませんが、妥当な推定値は 8 です (特定の構成によって生成される数として別の回答でも示されています)。

Ex2 の場合、オブジェクトの最小数は 2 です。コンパイラは、StringBuilder を異なるセマンティクスを持つカスタム バージョンに置き換えたかどうかを知る方法がないため、最適化しません。バッキング配列を一度に 1 文字ずつ展開する非常にメモリを節約する StringBuilder 実装の場合、最大値は約 6 ですchar[]が、ほとんどの場合は 2 になります。

于 2013-08-19T02:33:42.130 に答える