💬
[Kotlin] String template の仕組み
Kotlin String template の仕組み
つまり
- template の構成によって、バイトコードが全然違う
- 文字列を後置する場合には、単純な文字列 + 演算で計算
- 文字列の途中と置換する場合には、StringBuilder で計算
実験コード
fun main(){
val name = "Tom"
val greeting1 = "Hello ${name}"
val greeting2 = "Hello ${name} !"
}
$ kotlinc ./StringTemplate.kt -include-runtime -d ./StringTemplate.jar; unzip -o StringTemplate.jar; javap -p -v -s -constants -c StringTemplateKt.class
(省略)
public static final void main();
descriptor: ()V
flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
Code:
stack=2, locals=3, args_size=0
0: ldc #8 // String Tom
2: astore_0
3: ldc #10 // String Hello
5: aload_0
6: invokestatic #16 // Method kotlin/jvm/internal/Intrinsics.stringPlus:(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
9: astore_1
10: new #18 // class java/lang/StringBuilder
13: dup
14: invokespecial #21 // Method java/lang/StringBuilder."<init>":()V
17: ldc #10 // String Hello
19: invokevirtual #25 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: aload_0
23: invokevirtual #25 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
26: ldc #27 // String !
28: invokevirtual #25 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
31: invokevirtual #31 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
34: astore_2
35: return
(省略)
greeting1
は kotlin/jvm/internal/Intrinsics.stringPlus
で計算されます。
これは、 Hello
文字列に ${name}
文字列を後置しているからですね。
一方で、greeting2
は StringBuilder を使って作成されます。
JVM での一般的な文字列の作成方法ですね。安直には、 String.format
が利用されそうですが、遅いと噂なのでこういう実装になっているのかもしれません。
Java 書くときは「この API は遅い」的な知識が要求されるけど、Kotlin を書くときは高級に?宣言的に?書きつつコンパイラがベストプラクティスを適用してくれているように感じる。
Discussion