「古い」方法は、一連のStringBuilder
指向の操作を出力します。このプログラムを考えてみましょう:
public class Example {
public static void main(String[] args)
{
String result = args[0] + "-" + args[1] + "-" + args[2];
System.out.println(result);
}
}
これをJDK 8以前でコンパイルしてjavap -c Example
からバイトコードを確認すると、次のようになります。
パブリッククラスの例{
public Example();
コード:
0:aload_0
1:invokespecial#1 //メソッドjava / lang / Object。 "<init>" :()V
4:戻る
public static void main(java.lang.String []);
コード:
0:新しい#2 //クラスjava / lang / StringBuilder
3:重複
4:invokespecial#3 //メソッドjava / lang / StringBuilder。 "<init>" :()V
7:aload_0
8:iconst_0
9:aaload
10:invokevirtual#4 //メソッドjava / lang / StringBuilder.append:(Ljava / lang / String;)Ljava / lang / StringBuilder;
13:ldc#5 //文字列-
15:invokevirtual#4 //メソッドjava / lang / StringBuilder.append:(Ljava / lang / String;)Ljava / lang / StringBuilder;
18:aload_0
19:iconst_1
20:aaload
21:invokevirtual#4 //メソッドjava / lang / StringBuilder.append:(Ljava / lang / String;)Ljava / lang / StringBuilder;
24:ldc#5 //文字列-
26:invokevirtual#4 //メソッドjava / lang / StringBuilder.append:(Ljava / lang / String;)Ljava / lang / StringBuilder;
29:aload_0
30:iconst_2
31:aaload
32:invokevirtual#4 //メソッドjava / lang / StringBuilder.append:(Ljava / lang / String;)Ljava / lang / StringBuilder;
35:invokevirtual#6 //メソッドjava / lang / StringBuilder.toString :()Ljava / lang / String;
38:astore_1
39:getstatic#7 //フィールドjava / lang / System.out:Ljava / io / PrintStream;
42:aload_1
43:invokevirtual#8 //メソッドjava / io / PrintStream.println:(Ljava / lang / String;)V
46:戻る
}
ご覧のとおり、を作成してStringBuilder
を使用していappend
ます。組み込みバッファーのデフォルトの容量はStringBuilder
16文字しかないため、これはかなり非効率的であることが有名です。コンパイラーが事前にさらに割り当てることを知る方法がないため、最終的には再割り当てする必要があります。また、メソッド呼び出しの集まりでもあります。(ただし、JVMはこれらの呼び出しパターンを検出および書き換えて、より効率的にすることができることに注意してください。)
Java 9が生成するものを見てみましょう。
パブリッククラスの例{
public Example();
コード:
0:aload_0
1:invokespecial#1 //メソッドjava / lang / Object。 "<init>" :()V
4:戻る
public static void main(java.lang.String []);
コード:
0:aload_0
1:iconst_0
2:aaload
3:aload_0
4:iconst_1
5:aaload
6:aload_0
7:iconst_2
8:aaload
9:invokedynamic#2、0 // InvokeDynamic#0:makeConcatWithConstants:(Ljava / lang / String; Ljava / lang / String; Ljava / lang / String;)Ljava / lang / String;
14:astore_1
15:getstatic#3 //フィールドjava / lang / System.out:Ljava / io / PrintStream;
18:aload_1
19:invokevirtual#4 //メソッドjava / io / PrintStream.println:(Ljava / lang / String;)V
22:戻る
}
ああ、でもそれはもっと短いです。:-)これは、Javadocでこれを示すmakeConcatWithConstants
from への単一の呼び出しを行いますStringConcatFactory
。
既知の型の既知の数の引数を効率的に連結するために使用できる文字列連結メソッドの作成を容易にするメソッド。これらのメソッドは通常、Javaプログラミング言語の文字列連結機能をサポートするために、invokedynamic
呼び出しサイトのブートストラップメソッドとして使用されます。