B-Teck!

お仕事からゲームまで幅広く

【Kotlin】KotlinのReified type parametersについて

前置き

【Kotlin】Kotlin+JacksonでJSONをparseする - B-Teck! のparseJSONがなぜ型情報を使えるのか
会社でJavaを書いている人にこの話をしたところ驚かれたので。

Genericsとtype erasure

JVMにおけるジェネリクスはJava1.4以前のバイナリとの仕様互換のため、
コンパイル時には型情報が削除され、実行時にはその型情報についてアクセスすることができない。
Javaではよく知られた仕様であり、Kotlinでも同様の動作をしている。

イレイジャについてより詳しく知りたければ下記の記事などを参照
贖罪のイレイジャ - プログラマーの脳みそ

inline関数とReified type parameters

ただKotlinでは、関数をinlineで宣言した上で、型パラメータをreifiedとすることで、
実行時に型引数を参照するような形で書くことができる。

inline関数

inline修飾子を付けた関数を、inline関数と呼ぶ。
この修飾子のついた関数は、コンパイル時に呼び出し元にコードとして展開され、
関数呼び出しの形ではなくなる。C言語のマクロに似ているらしい。
関数呼び出しがなくなることで処理速度の向上が見込めるが、
コードとして展開されるためバイナリのサイズは大きくなる。

Reified type parameters

inlineのジェネリクス関数の型にreifiedキーワードを用いることで、
実行時に扱っている型の情報を扱うことができるようになる。
何が嬉しいかというと、与えられたTの型によってJSONをパースするclassを切り替えたいとかのときに、
外から型を渡してあげることができたり、
ジェネリクスを扱う関数の中でTでキャストとか、is Tとかしたりできる。
Inline Functions and Reified Type Parameters - Kotlin Programming Language
より詳細な仕様は下記
kotlin/reified-type-parameters.md at master · JetBrains/kotlin · GitHub

Javaからは呼べない

JavaからKotlinのinline関数を呼び出した場合、Javaのコンパイラではstatic関数を呼び出すようにコンパイルされる。
Call Kotlin inline function from Java - Stack Overflow
reifiedはコードがインライン展開されていることを前提としているため、エラーとなってしまう(らしい) How can I call Kotlin methods with reified generics from Java? - Stack Overflow

まとめ

  • Kotlinではinline関数とreifiedを組み合わせて利用することで、ジェネリクスでも型情報を扱える
  • JavaからReified type parametersを利用したメソッドを呼び出した場合、エラーとなってしまう