2

インスタンスメソッドを実行すると、連結に関してb/w 1と2に違いはありますか。どちらの場合も、最終的には1つのオブジェクト、つまり「abc」のみが構築されることを意味します。はい、唯一の違いは、テストがpermgenスペース内にあり、スレッドがインスタンスメソッドから出てきてもxがガベージコレクションされることです。構築されるオブジェクトの数の条件は同じになります。右?

// option 1
String test="a"+"b"+"c";

// option 2  
StringBuffer x = new StringBuffer().append("a").append("b").append("c").toString()

リンクhttp://docs.oracle.com/javase/7/docs/api/java/lang/StringBuffer.htmlを参照して、この結論に達しました。

4

6 に答える 6

8

リンクしたドキュメントが非常に古いことに最初に注意してください。Java 1.4.2用であることに注意してください。

J2SE 1.4.2 は、Java Technology End of Life (EOL) 移行期間にあります。EOL への移行期間は 2006 年 12 月 11 日に始まり、J2SE 1.4.2 がサービス ライフ終了 (EOSL) に達する 2008 年 10 月 30 日に終了します。

ドキュメントの新しいバージョンでは、このステートメントは削除されています。ただし、注意が必要な別のステートメントが追加されています。

リリース JDK 5 の時点で、このクラスは、単一スレッドで使用するために設計された同等のクラス StringBuilder で補足されています。StringBuilder クラスは、同じ操作をすべてサポートしますが、同期を実行しないため高速であるため、通常はこのクラスよりも優先して使用する必要があります。


次に、参照するドキュメントに次のコードがあることに注意してください。

x = "a" + 4 + "c";

4タイプミスだけではありません。コンパイラは単一の文字列リテラルのみを使用するようにコードを変換するため、あなたの例は異なります。次の 2 行は同じです。

x = "a" + "b" + "c"; 
x = "abc";

文字列リテラルはインターンされます。


ただし、コンパイラが単一の文字列リテラルを使用できない一般的なケースでは、コンパイラは最初のバージョンを 2 番目のバージョンに変換しますStringBuilderが、より効率的であるため代わりに使用します。

于 2012-07-26T10:39:03.527 に答える
5

まず第一に、StringBuilder代わりにStringBuffer,を使用することStringBufferは現在非推奨です。

そして、あなたの質問については、最近ではそれほど重要ではありません.コンパイラは自動的に文字列の連結をStringBuilderに変換します.

使用するケースは 2 つだけです。1 つ目は、コードの読みやすさです (たとえば、SQL クエリのような長い文字列を作成している場合)。2 つ目は、ループ内で文字列を連結する場合、コンパイラは常にループを通過するたびに新しい StringBuilder インスタンスを作成するため、注意が必要です。

于 2012-07-26T10:42:24.180 に答える
4

まず第一に、StringBuilderis toは toです: 同期されStringBufferていないため、優先する必要があります。ArrayListVector

最初の文字列はコンパイル時に完全に構​​築され、文字列リテラルとして格納されます。このリテラルはプール内に保持され、test変数は常に同じ String インスタンスを指します。

2 番目のスニペットは、実行時に 3 つの文字列リテラルを動的に連結します。呼び出されるたびに新しい String インスタンスを返します。

于 2012-07-26T10:42:12.437 に答える
4

2 つの例で生成されたバイトコードを見ると、最初の文字列は "abc" 文字列リテラルに変換されますが、2 番目の文字列は StringBuilder メソッドを呼び出します。System.out.println(test == "abc");true を出力する で実際にテストできます。

   0: ldc           #2                  // String abc
   2: astore_1      
   3: new           #3                  // class java/lang/StringBuffer
   6: dup           
   7: invokespecial #4                  // Method java/lang/StringBuffer."<init>":()V
  10: ldc           #5                  // String a
  12: invokevirtual #6                  // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
  15: ldc           #7                  // String b
  17: invokevirtual #6                  // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
  20: ldc           #8                  // String c
  22: invokevirtual #6                  // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
  25: invokevirtual #9                  // Method java/lang/StringBuffer.toString:()Ljava/lang/String;
  28: astore_2      
于 2012-07-26T10:42:36.033 に答える
3

コンパイル時に 3 つの文字列リテラルを連結するこの特定のケースでは、コンパイラは次のように入力した場合と同じようにコードを生成します。

String test="abc";

したがって、中間オブジェクトを完全に回避します。

于 2012-07-26T10:42:07.170 に答える
0

メモリ使用量の場合、どちらも同じだと思います。

于 2012-07-26T10:39:56.087 に答える