5.26-5.29汎用型の使用
3407 ワード
次のクラスでは、汎用型を使用します.
次のテストコードを使用してエラーを報告します.
以上のテストコードは、Container宣言を使用しているため、addAll()はListタイプのパラメータ値のみを受け入れます.したがって、IntegerはNumberのサブクラスであるにもかかわらず、1つのListタイプのパラメータが入力されるとエラーが表示されます.
汎用ワイルドカードを使用して汎用メソッドの適応性を高めることができます.基本原則はPECS(producer-extends,consumer-super)です.前述の例では、addAll()から入力されたlistパラメータはcontainerオブジェクトにデータを提供するので、このlistオブジェクトはcontainerに対してproducerです.同様に、removeAll()が入力したlistパラメータはcontainerを使用して削除されたオブジェクトであるため、このlistはconsumerです.以上の原則に基づいて、修正方法は以下の通りである.
すべてのComparable、ComparatorはConsumerです.このインタフェースを使用する場合は、次の宣言を使用します.
以下のテストunion()のコードはエラーを報告し、入力されたパラメータはそれぞれList、Listタイプであり、コンパイラはどのパラメータタイプを使用すべきか分からない(なぜコンパイラは結果を返すタイプListから実際のパラメータタイプを取得しないのか?)
コンパイラが使用する実際のパラメータタイプをNumberとして明示的に指定するには、次のように変更します.
汎用型を使用すると、「コンテナ」が格納できる要素のタイプを制限できます.例えば、Listの制限コンテナListには、タイプEの要素しか格納できません.Mapタイプのコンテナと同様に、次のインタフェースキーのタイプがClassであり、valueがT、すなわちvalue.classタイプがkeyと同じであることをtypesafe heterogeneous containerと呼ぶ.
注意:Class.asSubclass()を呼び出してタイプ変換できます.
実装クラス:
public class Container <E>{
private List<E> elements=new ArrayList<E>();
public void addAll(List<E> list){
elements.addAll(list);
}
public void removeAll(List<E> list){
list.addAll(elements);
elements.clear();
}
public static <T> List<T> union(List<? extends T> list1,List<? extends T> list2){
return null;
}
}
次のテストコードを使用してエラーを報告します.
List<Integer> list1=Arrays.asList(1,2,3);
Container<Number> container=new Container<Number>();
container.addAll(list1);//
以上のテストコードは、Container
汎用ワイルドカードを使用して汎用メソッドの適応性を高めることができます.基本原則はPECS(producer-extends,consumer-super)です.前述の例では、addAll()から入力されたlistパラメータはcontainerオブジェクトにデータを提供するので、このlistオブジェクトはcontainerに対してproducerです.同様に、removeAll()が入力したlistパラメータはcontainerを使用して削除されたオブジェクトであるため、このlistはconsumerです.以上の原則に基づいて、修正方法は以下の通りである.
public void addAll(List<? extends E> list){
elements.addAll(list);
}
public void removeAll(List<? super E> list){
list.addAll(elements);
elements.clear();
}
すべてのComparable、ComparatorはConsumerです.このインタフェースを使用する場合は、次の宣言を使用します.
public <T extends Comparable<? super T>> T max(List<T> list){
return null;
}
以下のテストunion()のコードはエラーを報告し、入力されたパラメータはそれぞれList
List<Integer> list1=Arrays.asList(1,2,3);
List<Double> list2=Arrays.asList(4.0d,5.0d,6.0d);
List<Number> list=Container.union(list1, list2);//
コンパイラが使用する実際のパラメータタイプをNumberとして明示的に指定するには、次のように変更します.
List<Number> list=Container.<Number>union(list1, list2);
汎用型を使用すると、「コンテナ」が格納できる要素のタイプを制限できます.例えば、List
注意:Class.asSubclass()を呼び出してタイプ変換できます.
public class Favorites {
public <T> void putFavorite(Class<T> type, T instance);
public <T> T getFavorite(Class<T> type);
}
実装クラス:
public class Favorites {
private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>();
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
favorites.put(type, type.cast(instance));// type
}
public <T> T getFavorite(Class<T> type) {
return type.cast(favorites.get(type));
}
}