【かたしょうきょ】

型消去 とは?

最終更新:
💡 コンパイル時に確かめた型の情報を、実行用の形へ整理する

型消去は、実行時に型を表す方法から一部の型情報を取り除く仕組みです。Javaのジェネリクスを中心に、Objectや境界への置換、残る型情報、TypeScriptとの違いを説明します。

📌 このページのポイント
Java:消える情報と、残る情報ソースでの型List<String>型引数を検査消去後の型List型引数を取り除く型パラメーターの置換T → ObjectT extends Number → Number✓ オブジェクトのクラスは残るすべての型情報が消えるわけではない
Javaの型消去の例。必要なキャストなどを補い、型引数ごとに別のクラスを作りません。
ひよこ ひよこ
Javaは、全部Objectになってしまうの?
ペンギン先生 ペンギン先生
そうではないよ。ジェネリクスの型パラメーターを置き換える仕組みで、境界がなければObject、たとえばT extends NumberならNumberになる。オブジェクト自体のクラスや、通常のメソッドの型が全部消えるわけではないんだ。
ひよこ ひよこ
List<String>とList<Integer>は、別のクラス?
ペンギン先生 ペンギン先生
型引数ごとに新しいクラスを作る方式ではないよ。コンパイラーは型を検査し、必要なキャストやブリッジメソッドを補う。リストからStringとして取り出す処理も、その変換を含む形になる。同じクラスを使うことと、コンパイル時の型チェックがないことは別だね。
ひよこ ひよこ
実行時に、Stringだけのリストか判定できる?
ペンギン先生 ペンギン先生
Object型で受け取った値に対してinstanceof List<String>を使い、型引数をまとめて調べることはできないよ。List<?>かどうかと、各要素がどのクラスかの確認は別。なおJava 16以降には、コンパイル時の型から安全に判断できる一部のパラメーター付きinstanceofが許されるため、「すべて禁止」とも言い切れないんだ。
ひよこ ひよこ
型の情報は、どこにも残らない?
ペンギン先生 ペンギン先生
クラスそのものの情報は残るよ。宣言のジェネリクス情報をリフレクションで参照できる場合もある。ただし、それで一般のListオブジェクトの全要素がStringだと保証できるわけではない。宣言の情報と、実際の値の検査を分けよう。
ひよこ ひよこ
TypeScriptも、同じ仕組み?
ペンギン先生 ペンギン先生
TypeScriptはJavaScriptを出力するときに型注釈を取り除くよ。たとえば引数をstringと書いても、その注釈だけで外部入力が文字列かを実行時に検査してはくれない。必要なら実際の値を検証する。Javaの型パラメーターの置換と、TypeScriptの型注釈の除去は、どちらも何が残るかを確認して理解しよう。
ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「型消去」って出てきたら「実行用のコードでは、一部の型情報を取り除く仕組み」と思えばだいたいOK!
📖 おまけ:英語の意味
「Type Erasure」 = 型消去
💬 Erasureは消去。ここでは主にJavaのジェネリクスの実装を説明するよ。何が消えるかは言語や仕組みで違うんだ。

参考資料

← 用語集にもどる