Javaタイプ消去と汎用
5334 ワード
Javaの詳細については、文集「Javaの詳細」を参照してください.
タイプシステム
Liskovリ氏置換の原則は,子クラスが親クラスに置換できることである.が に伝達することができる.が を投げ出す可能性がある.
タイプ消去タイプErasure
Javaの汎用性はコンパイラ階層で実現される.コンパイル生成されたバイトコードには汎用型のタイプパラメータが含まれておらず、タイプパラメータはコンパイル時に削除されます.例えば、
タイプ消去の基本手順:コード内のタイプパラメータを特定のクラスに置き換え、
汎用型型パラメータはクラスのみ、例えば である.型のパラメータは、例えば のように複数あることができる.
汎用性のメリットコンパイル時により強力なタイプ検出.Javaコンパイラは汎用型に強力なタイプ検出を適用し、コードがタイプセキュリティに違反するとエラーが発生します.コンパイル時エラーの修復は、実行時エラーの修復よりも容易です.実行時エラーが検出されにくいためです.
例えば、方法は、
汎用型で実現すると、コンパイル時にタイプの検出が行われます.たとえば、コンパイルエラーが発生します.は、自動および暗黙的なタイプ変換を提供する、例えば、関数が戻るときに表示する必要のないタイプ変換 を提供する.は、C++のテンプレート と同様の汎用アルゴリズムを実現する.
汎用的な奇妙な特性汎用クラスには、独自の 汎用クラスの静的変数は、すべてのインスタンスで共有される. 汎用クラスのタイプパラメータは、異常処理のcatchでは使用できません.例外処理はJVM実行時に行われるため、タイプパラメータは消去されます.
VS >
相違点: である. に用いる.
同じ点:上界と下界を指定できます.たとえば、
汎用クラス
例:
Java 7の汎用タイプ推定の改善
上記のコードでは、
Java 7では、この方法が改良され、
汎用メソッド
例:
汎用クラスの使用 などの特定のタイプを指定します.は、
タイプシステム
Liskovリ氏置換の原則は,子クラスが親クラスに置換できることである.
Object
の参照を必要とする場合、String
のオブジェクトString
の参照を必要とする場合、Object
のオブジェクトに転送するには強制的なタイプ変換が必要であり、実行時にClassCastException
タイプ消去タイプErasure
Javaの汎用性はコンパイラ階層で実現される.コンパイル生成されたバイトコードには汎用型のタイプパラメータが含まれておらず、タイプパラメータはコンパイル時に削除されます.例えば、
List
およびList
は、コンパイル後、いずれもList
になる.タイプ消去の基本手順:コード内のタイプパラメータを特定のクラスに置き換え、
<>
の内容を削除します.汎用型
List
、単純タイプ、例えばList
HashMap
汎用性のメリット
例えば、方法は、
String
オブジェクトを入力し、String
オブジェクトを出力し、Integer
オブジェクトに強制的に変換するコードである.このコードコンパイルは、Object
のサブクラスであるため、実行時にClassCastException
が生成される.public static Object setAndReturn(Object obj) {
return obj;
}
public static void main(String[] args) {
Integer i = (Integer) setAndReturn(new String("abc"));
}
汎用型で実現すると、コンパイル時にタイプの検出が行われます.たとえば、コンパイルエラーが発生します.
public static T setAndReturn(T t) {
return t;
}
public static void main(String[] args) {
Integer i = (Integer) setAndReturn(new String("abc"));
}
setAndReturn(new Integer("123"));
public static T setAndReturn(T t) {
return t;
}
public static void main(String[] args) {
// = setAndReturn(new Integer("123"));
Integer i = setAndReturn(new Integer("123"));
}
汎用的な奇妙な特性
Class
オブジェクトはありません.すなわち、List.class
は存在せず、List.class
のみが存在する.VS >
相違点:
は汎用的な定義に用いる、例えばclass MyGeneric {...}
>
は、汎用的な宣言、すなわち、汎用的な使用、例えばMyGeneric> g = new MyGeneric<>();
同じ点:上界と下界を指定できます.たとえば、
class MyGeneric {...}
class MyGeneric {...}
MyGeneric extends Collection> g = new MyGeneric<>();
MyGeneric super List> g = new MyGeneric<>();
汎用クラス
例:
public class Generic_Test {
public static void main(String[] args) {
MyGeneric g1 = new MyGeneric(new String("123"));
g1.print();
MyGeneric g2 = new MyGeneric(new Integer("123"));
g2.print();
}
}
class MyGeneric {
private T t;
public MyGeneric(T t) {
this.t = t;
}
public void print() {
System.out.println(t.getClass().getName());
}
}
Java 7の汎用タイプ推定の改善
上記のコードでは、
MyGeneric g1 = new MyGeneric(new String("123"));
です.宣言と付与の両方に汎用型
を付ける必要があることがわかる.Java 7では、この方法が改良され、
MyGeneric g1 = new MyGeneric<>(new String("123"));
という文を使用して宣言および付与することができる.この文では、コンパイラは、変数宣言時の汎用タイプに基づいて、MyGeneric
をインスタンス化した汎用タイプを自動的に推定する.汎用メソッド
例:
public static void print(T t) {
System.out.println(t.getClass().getName());
}
public static void main(String[] args) {
print(new String("123"));
print(new Integer("123"));
}
汎用クラスの使用
List
などの未知のタイプを指定します.List>
がList>
に等しくないのはList