💬

[Kotlin] String template の仕組み

2022/02/26に公開

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
(省略)

greeting1kotlin/jvm/internal/Intrinsics.stringPlus で計算されます。
これは、 Hello 文字列に ${name}文字列を後置しているからですね。

一方で、greeting2 は StringBuilder を使って作成されます。
JVM での一般的な文字列の作成方法ですね。安直には、 String.format が利用されそうですが、遅いと噂なのでこういう実装になっているのかもしれません。
Java 書くときは「この API は遅い」的な知識が要求されるけど、Kotlin を書くときは高級に?宣言的に?書きつつコンパイラがベストプラクティスを適用してくれているように感じる。

Discussion