0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ジェネリック型のタイプ情報を取得する

Posted at

任意型のデータをその実際の型情報を元に処理を行う場合、型情報としてTypeのインスタンスが必要になることがあります。
例えば、Stringクラスを表すType<String>のインスタンスは

String::class.java

とすることでClass<String>を取得することができます。(ClassクラスはTypeインターフェースを実装しています)しかし、ジェネリクス型のタイプパラメータを含めたTypeのインスタンスは、直接取得する手段が提供されていません。

例えば、List<String>のTypeType<List<String>>が必要な場合、

List<String>::class.java

という記述はコンパイルエラーとなります。
このタイプパラメータを含めたType情報はParameterizedTypeとなります。

どうやって取得すれば良いでしょうか?

アブストラクトクラスを実装して取得する

ParameterizedTypeを返すメソッドとして、Classクラスの、getGenericSuperclass()があります。
これはそのクラスの親クラスの情報となりますので、Hoge<T>を継承したFugaから呼び出した場合に、Type<Hoge<T>>を得ることができます。
そして、ParameterizedTypeはgetActualTypeArguments()というメソッドを持っており、そのジェネリクス型の型パラメータのTypeを取得することができ、この型引数もジェネリクス型の場合、ParameterizedTypeが返却されます。

そこで、型引数を持つabstractクラスを作成し、その型引数に取得したいジェネリクス型を指定して継承を行い、getGenericSuperclass()でParameterizedTypeを取得し、getActualTypeArguments()[0]で一つ目の型引数のTypeを取得する。という手順を踏むことで、ジェネリクス型のTypeを取得することができます。

以下のような、abstractクラスを作成し

abstract class TypeToken<T> {
    fun getType(): Type =
        (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
}

以下のように、インライン実装してgetType()を呼び出すことで取得できます。

object : TypeToken<List<String>>() {}.getType()

Kotlinではインライン関数を使って、以下のように、actualTypeOf()メソッドを作成すると

inline fun <reified T: Any> actualTypeOf(): Type = object : TypeToken<T>() {}.getType()

abstract class TypeToken<T> {
    fun getType(): Type =
        (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
}
actualTypeOf<List<String>>()

と、よりスマートに取得できます。

KTypeから変換する

Javaの範囲ではややこしい実装が必要ですが、現在のKotlinでは、typeOf()というKTypeを取得するメソッドが用意されています。KTypeからTypeを取得することができるので

@OptIn(ExperimentalStdlibApi::class)
typeOf<List<String>>().javaType

とすることで、Type<List<String>>のインスタンスを取得することができます。javaTypeはまだ実験段階のため、@OptIn(ExperimentalStdlibApi::class)をつけて利用する必要があります。

Experimentalが外れれば、この方法でよさそうです


以上です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?