akios @ ウィキ
4.7. 具象可能型
最終更新:
akios
-
view
4. 型と値と変数
4.1. 型と変数の種類
4.2. プリミティブ型と値
4.3. 参照型と値
4.4. 型変数
4.5. 引数付き型
4.6. 型の抹消
4.7. 具象可能型
いくつかの型の情報はコンパイル中に抹消されるため、実行時に全ての型が利用可能であるとは限りません。実行時に完全な形で利用可能な型を具象可能型(reifiable type)と呼びます。
次のいずれか1つの条件を満たす場合のみ、型は具象可能であるといいます。:
- 非ジェネリッククラスやインタフェース型宣言を参照する
- 全ての型引数が制限なしのワイルドカードである引数付き型である
- 未加工型である
- プリミティブ型である
- 構成要素の型が具象可能である配列型である
- 入れ子型で、"."で分割された各型Tに対してT自身が具象可能
例えば、ジェネリッククラスX<T>がジェネリックメンバークラスY<U>を持っている場合、X<?>とY<?>は具象可能であるためX<?>.Y<?>型も具象化可能です。X<?>.Y<Object>はY<Object>が具象可能でないため具象可能ではありません。
交差型は具象可能ではありません。
ジェネリック型を全て具象可能にしないという決定は最も重要なものの1つで、Javaプログラミング言語のシステムに関係する論争となる設計決定です。
究極的には、この決定の最も重要な意義は既存コードとの互換性です。素直な感覚では、ジェネリックスのような新しい構成物の追加は既存コードに影響を与えません。Javaプログラミング言語それ自体は初期のバージョンとの互換性があります。以前のバージョンで書かれた全てのプログラムは新しいバージョンで引き続き動作します。しかしながら、言語の互換性と呼んでよいこの概念は純粋な理論的意味でです。実際のプログラム("Hello World"のようなささいなものさえ)は複数のコンパイル単位で構成されます。その内いくつかはJava SEプラットフォームで提供しているものです(java.langやjava.utilなど)。実際に、最低限の要件はプラットフォーム互換性です。これはJava SEプラットフォームの以前のバージョンで書かれたプログラムが新しいバージョンでも機能的に何の変更もなく動作するということです。
プラットフォーム互換性を提供する1つの方法は、機能を変更しないで、新たな機能だけ追加することで、既存プラットフォームをそのまま維持しておくことです。例えば、既存のjava.util内のCollections階層構造を変更するよりもむしろジェネリクスを活用する新たなライブラリを導入するという方法があります。
そのようなスキームの欠点はCollectionライブラリの既存クライアントが新たなライブラリに移行するのことが極めて難しくなる点です。Collectionsは独立して開発されたモジュール間でデータを交換するのに使用されます。ベンダーが新たなジェネリックライブラリに移行すると決定したら、そのベンダーはクライアントの互換性を保つため、2つのバージョンのコードを提供しなければなりません。他のベンダーのコードに依存するライブラリはその供給者のライブラリが更新されるまでジェネリクスを使用するように変更することはできません。2つのモジュールが相互に依存していたら、変更は同時に行わなければなりません。
明らかに、上で記述したプラットフォーム互換性はジェネリクスのような普及する新機能を採用するための現実的なパスではありません。従って、ジェネリック型システムの設計は移行互換性をサポートするように努めています。移行互換性は、独立して開発されたソフトウェアモジュール間の人目を引く依存関係なしに既存コードの進化でジェネリクスの利用することを認めます。
ジェネリック型システムの完全で堅固な具体化を行う移行互換性の代価は、少なくとも移行中の場合には、とても払いきれるものではありません。