JavacコンパイラがStringBuilder
/StringBuffer
を使用して文字列連結+
を変換できることを知っていますが、知りたいのですがどのバージョンから開始これ変更が導入されましたか?
私はこのサンプルコードを使用しています:
public class Main {
public static void main(String[] args) {
String a = args[0];
String s = "a";
s = s + a;
s = s + "b";
s = s + "c";
s = s + "d";
s = s + "e";
System.out.println(s);
}
}
これまで、javac 1.8.0_121
、javac 1.6.0_20
、javac 1.5.0_22
、およびJava 1.4.2_19
で試しました。
javap -c
から1.4.2_19
を使用して表示されるバイトコードのサンプルを次に示します。
6: astore_2
7: new #3; //class StringBuffer
10: dup
11: invokespecial #4; //Method Java/lang/StringBuffer."<init>":()V
14: aload_2
15: invokevirtual #5; //Method Java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
18: aload_1
19: invokevirtual #5; //Method Java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
22: invokevirtual #6; //Method Java/lang/StringBuffer.toString:()Ljava/lang/String;
4つのバージョンすべてがStringBuilder/StringBuffer最適化を使用しているようですので、知りたいのですがどのJavacバージョンから開始この変更が導入されましたか?
バージョン1の言語仕様 からの引用です。
実装は、中間の
String
オブジェクトを作成して破棄することを回避するために、変換と連結を1つのステップで実行することを選択できます。繰り返される文字列連結のパフォーマンスを向上させるために、JavaコンパイラはStringBuffer
クラス(§20.13)または同様の手法を使用して、式の評価によって作成される中間のString
オブジェクトの数を減らすことができます。 。
当時、彼らはStringBuffer
の代わりにStringBuilder
を持っていました。
また、JDK1.0.2の StringBuffer
からの引用:
このクラスは、文字の拡張可能なバッファーです。これは主に文字列を作成するために使用されます。コンパイラはこれを使用して「+」演算子を実装します。
Java言語仕様、初版(1996年から)を調べました。簡単な発見ではありませんが、 ここにあります 。連結最適化に関する一節もありました。その後:
実装は、中間のStringオブジェクトを作成して破棄することを回避するために、変換と連結を1つのステップで実行することを選択できます。繰り返される文字列連結のパフォーマンスを向上させるために、JavaコンパイラはStringBufferクラス(§20.13)または同様の手法を使用して、式の評価によって作成される中間Stringオブジェクトの数を減らすことができます。 。
その場合、仕様はStringBuffer
に関連しますが、StringBuilder
(現在のJLSの表現で参照されている)は、メソッドが同期されていないため、パフォーマンスが優れていると見なされる場合があります。
ただし、これは、常にが実行されているため、最適化に依存する必要があることを意味するものではありません。たとえば、ループ内の文字列の連結は最適化されません。
JLSはすでにいくつかの回答で与えられています。 StringBuffer( https://docs.Oracle.com/javase/8/docs/api/Java/lang/StringBuffer.html )が1.0以降存在していたことを強調したいのですが
StringBuilder( https://docs.Oracle.com/javase/8/docs/api/Java/lang/StringBuilder.html )はバージョン1.5で提供されました。それぞれのjavadocのsince:
セクションを参照してください。
これは質問に答えませんですが、jdk-9ではこのStringBuilder::append
は許可された戦略の1つであるという全体的なポイントを追加したいだけですが、デフォルトのものではありません。
private enum Strategy {
/**
* Bytecode generator, calling into {@link Java.lang.StringBuilder}.
*/
BC_SB,
/**
* Bytecode generator, calling into {@link Java.lang.StringBuilder};
* but trying to estimate the required storage.
*/
BC_SB_SIZED,
/**
* Bytecode generator, calling into {@link Java.lang.StringBuilder};
* but computing the required storage exactly.
*/
BC_SB_SIZED_EXACT,
/**
* MethodHandle-based generator, that in the end calls into {@link Java.lang.StringBuilder}.
* This strategy also tries to estimate the required storage.
*/
MH_SB_SIZED,
/**
* MethodHandle-based generator, that in the end calls into {@link Java.lang.StringBuilder}.
* This strategy also estimate the required storage exactly.
*/
MH_SB_SIZED_EXACT,
/**
* MethodHandle-based generator, that constructs its own byte[] array from
* the arguments. It computes the required storage exactly.
*/
MH_INLINE_SIZED_EXACT
}
これは実際には文字列連結のinvokedynamic
バイトコードであるため、実装はコンパイラではなくJRE固有になりました。デフォルトの戦略は次のとおりです:MH_INLINE_SIZED_EXACT