4

Stringは不変であり、StringBuilderまたはStringBufferをいつ使用するかについては知っています。また、これら2つのスニペットのバイトコードは同じになることも読みました。

//Snippet 1
String variable = "text";
this.class.getResourceAsStream("string"+variable);

//Snippet 2
StringBuilder sb = new StringBuilder("string");
sb.append("text");
this.class.getResourceAsStream(sb.toString());

しかし、私は明らかに何か問題があります。EclipseでSnippet1を介してデバッグする場合、実際にはStringBuilderコンストラクターとappendメソッドに移動します。バイトコードがどのように解釈され、デバッガーがソースコードの行をどのように参照するかについての詳細が欠けていると思います。誰かがこれを少し説明できれば、私は本当に感謝します。また、JVM固有のものとそうでないもの(たとえば、Oracleのv6を実行している)を指摘できるかもしれません。ありがとうございます。

4

2 に答える 2

8

文字列の連結をデバッグするときにStringBuilderがポップアップするのはなぜですか?

文字列の連結(「+」演算子を使用)は通常、StringBufferまたはStringBuilderを使用して連結を行うコードにコンパイルされるためです。JLSは、この動作を明示的に許可します。

「実装は、中間のStringオブジェクトの作成と破棄を回避するために、変換と連結を1つのステップで実行することを選択できます。繰り返される文字列連結のパフォーマンスを向上させるために、JavaコンパイラはStringBufferクラスまたは同様の手法を使用して式の評価によって作成される中間文字列オブジェクト。」 JLS15.18.1

(コードがではStringBufferなくを使用しているStringBuilder場合は、おそらく、非常に古いJavaコンパイラを使用してコンパイルされたか、非常に古いターゲットJVMを指定したためです。StringBuilderクラスはJavaに比較的追加されています。古いバージョンのJLS IIRCStringBufferの代わりに言及するために使用されます。)StringBuilder


また、JVM固有のものとそうでないものを指摘できるかもしれません。

生成されるバイトコードは"string" + variable"、Javaコンパイラが連結を処理する方法によって異なります。(実際、生成されるすべてのバイトコードはある程度Javaコンパイラに依存します。JLSおよびJVMの仕様では、生成する必要のあるバイトコードは規定されていません。仕様では、プログラムの動作と個々のバイトコードの動作について詳しく説明しています。)


@supercatコメント:

文字列の連結で、たとえば2つのStringオブジェクトを受け入れ、適切な結合サイズのバッファを割り当ててそれらを結合するStringコンストラクタのオーバーロードが使用されないのはなぜでしょうか。または、より多くの文字列を結合する場合、String []を取るオーバーロード?結合する文字列への参照を含むString[]を作成することは、StringBuilderを作成することよりも費用がかからないはずです。また、完璧なサイズのバッキングストアを一度に作成できることは、パフォーマンスを簡単に向上させるはずです。

多分...しかし、私はおそらくそうではないと思います。これは、複雑なトレードオフを伴う複雑な領域です。文字列連結に選択された実装戦略は、さまざまなユースケースでうまく機能する必要があります。

私の理解では、元の戦略は、いくつかのアプローチを検討し、大規模な静的コード分析とベンチマークを実行して、どのアプローチが最適かを判断した後に選択されました。彼らはあなたが提案したすべての選択肢を検討したと思います。(結局のところ、彼らは/賢い人々でした...)

そうは言っても、Java 6、7、および8の完全なソースコードベースを利用できます。それはあなたがそれをダウンロードして、あなたの理論が正しいかどうか確かめるためにあなた自身のいくつかの実験を試みることができることを意味します。それらが...であり、それらが...であるという確かな証拠を収集できる場合は、OpenJDKチームにパッチを送信してください。

于 2012-08-05T09:18:27.243 に答える
1

@StephenC私はまだ説明に納得していません。コンパイラーは必要な最適化を実行できますが、Eclipseを介してデバッグする場合、ソースコードビューはコンパイラーコードから隠されており、コードのあるセクションを同じソースファイル内の別のコードにジャンプすることはできません。

質問の次の説明は、ソースコードとバイトコードが同期していないことを示しています。つまり、彼は最新のコードを実行していません。

When debugging through Snippet 1 in eclipse, I am actually taken to the StringBuffer constructor and to the append method

how the debugger refers back to the lines in the source code

于 2012-08-05T09:31:37.370 に答える