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?

【Kotlin】Kotlin の型消去(Type Erasure)

Posted at

はじめに

Kotlin のジェネリクスは Java と同様に「型消去方式」 を採用しています。
つまり、実行時にはジェネリクスの型情報が存在しません。
(コンパイル時だけ使われる仕組みです。)


1. 型消去とは何か?

定義:

型消去(Type Erasure) とは、
コンパイル後にジェネリクスの型パラメータ情報が削除され、
実行時には「生の型(raw type)」だけが残る仕組み。

つまり:

List<String> → List
List<Int>    → List

実行時にはどちらも 同じ型 (List) になります。


2. なぜ型が消えるのか?

Kotlin は JVM 上で動くため、
Java と同じ「型消去」方式 を採用しています。

Java が型消去を採用した理由:

  • 後方互換性(Generics 導入前の Java バイトコードと共存するため)
  • 実行時のオーバーヘッドを避けるため

したがって、JVM 上ではコンパイル時の型安全性のみ保証され、
実行時には型情報が削除されるという仕組みになっています。


3. 実際の例

例1:リストの型判定ができない

fun <T> check(list: List<T>) {
    if (list is List<String>) { // ❌ エラー!
        println("This is List<String>")
    }
}

エラーメッセージ:

Cannot check for instance of erased type 'List<String>'

理由:
実行時には List<T>List<String> も単なる List になるからです。


例2:実行時には型が同じになる

val list1 = listOf("a", "b")
val list2 = listOf(1, 2)

println(list1::class == list2::class) // true

実行時にどちらも java.util.ArrayList 型。
つまり List<String>List<Int> の区別は完全に失われます。


4. 型消去が起こるとどうなる?

状況 結果 理由
is List<String> ❌ 不可 実行時には List しか残らない
when (list) で型分岐 ❌ 不可 同上
T::class を使う ❌ 不可 型パラメータ T は消える
value!!::class を使う ✅ 可 実際のオブジェクトの型は保持されている

5. 実際に消える部分

fun <T> printList(list: List<T>) {
    println(list.javaClass.name)
}

出力:

java.util.Arrays$ArrayList

T の情報 (String, Int など) は完全に消え、
List の実装クラスだけが残ります。


6. 対処法:reified 型パラメータを使う

Kotlin では inline 関数+reified を使うことで、
実行時に型情報を保持 できます。

例:reified による型チェック

inline fun <reified T> checkType(value: Any) {
    if (value is T) {
        println("✅ value is ${T::class.simpleName}")
    } else {
        println("❌ value is not ${T::class.simpleName}")
    }
}

checkType<String>("Hello") // ✅ value is String
checkType<Int>("Hello")    // ❌ value is not Int

reified(具象化)によって、
コンパイル時に型情報がインライン展開され、
T::classis T が使えるようになります。


例:reified を使った JSON パース

inline fun <reified T> parseJson(json: String): T {
    val type = object : TypeToken<T>() {}.type
    return Gson().fromJson(json, type)
}

ランタイムでも T の型がわかるので、
List<User> などの複雑な型にも対応可能です。


7. Kotlin での型消去の整理表

項目 型情報保持 備考
コンパイル時 型安全にチェックされる List<String>List<Int> に代入できない
実行時 (JVM) 型情報は消える List<String>List<Int> は同一扱い
reified 使用時 型情報を埋め込める inline 関数でのみ可能

8. 型消去の利点と欠点

観点 利点 欠点
パフォーマンス バイトコードが軽量、後方互換性維持 -
型安全性 コンパイル時に検証可能 実行時に型を判定できない
柔軟性 既存 Java ライブラリとの互換性 型推論が限定される

まとめ

  • Kotlin(JVM)は ジェネリクス型消去方式 を採用
  • 実行時には型パラメータが削除され、List<String>List<Int> も同一型扱い
  • 型チェック(is List<String>)は不可能
  • 実行時にも型を使いたいときは inline fun <reified T> を使う

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?