Kotlinで型パラメータの型情報を取得する
フレームワークやライブラリの仕様で、Class
インスタンスが必要になる場合があります。
例: AndroidのIntent
を作る場合、jsonを特定の型にパースする場合など
JavaとKotlinではこのような場合にどのような違いがあるのか調べました。
Javaの場合
以下のようにAndroidのIntent
を作る際にActivity
のClass
を渡す場合
public <T> void startActivity(Context context, Class<T> clazz) { context.startActivity(new Intent(context, clazz)); } startActivity(this, MainActivity.class)
上のコードは問題なく動きますがジェネリクスで型が分かっているのに引数でClass
を渡しているのは冗長な気がします。
型パラメータからClass
を取得しようとするとどうなるのでしょうか
public <T> void startActivity(Context context) { context.startActivity(new Intent(context, T.class)); }
これはコンパイルエラーになります。これ以外の構文でもTからClass
を取得することはできません。
よってJavaでは型パラメータからClass
を取得することは基本的にはできず、引数としてClass
を渡さなければいけないのです。
Kotlinの場合
Kotlinの場合ではどうでしょうか?
Kotlinでは多少制約はありますが型パラメータのメソッド呼び出しやフィールドアクセスが可能です。
上のJavaコードをKotlinで書くと以下のようになります。
inline fun <reified T> startActivity(context: Context) { context.startActivity(Intent(context, T::class.java)) } startActivity<MainActivity>(this)
ポイントは
- inline関数にする必要がある
- 型パラメータに
reified
をつける - 型引数に
Nothing
や、List<String>
のように型パラメータ付きのクラス(Array
は除く)は使えない。
また、obj is T
のように型チェックも可能です。これもJavaではできないです。
最後に
今回はreified
の機能や使い方について調べてみました。
reified
を使うには制約がありますが、それは何故なのかも調べてみたいと思います。