Java汎用型の簡明な解釈
Java汎用由来の動機
Java汎用を理解する最も簡単な方法は、Javaタイプ変換(casting)の操作を節約する便利な文法と見なすことです.
以上のようなコードは,プログラマが手動でタイプ判断を行う必要はないが,汎用型のため,コンパイラ段階でタイプをチェックした.
汎用的な構成
汎型の構成からタイプ変数の概念を引き出した.Java言語仕様では、タイプ変数は制限のないフラグであり、次のような状況で発生します.汎用クラス宣言 汎用インタフェース宣言 汎用メソッド宣言 汎用コンストラクタ宣言 汎用クラスとインタフェース
汎用メソッドとコンストラクタ
汎用タイプのサブタイプ
このような3つの果物があるとします.
FujiApple,
Apple,
Fruit
FujiAppleはAppleのサブクラス、AppleはFruitのサブクラス、では
List,
List,
List,
三者の関係は何ですか.
上のコードは正しいですか?答えはコンパイルエラーです.
どうしてですか.次のコードを見てください
AppleがFruitのサブタイプであれば、ListがListのサブタイプであると考えると、Listは自然にaddイチゴをaddすることができる.
しかし、これは汎用型がタイプを決定するための公理に反している.これでリストにはいろいろなタイプが使われているので、出すときは手動で
タイプを判断しました.
したがって、ListはListとは関係ありません.
ワイルドカード
汎用オブジェクトの参照を上に作成
上記のコードでは、2つの汎用オブジェクトに継承関係を持たせる場合は、ワイルドカードを使用します.
「?extends」は汎用タイプのサブタイプ相関が現実になった:AppleはFruitのサブタイプ、ListはListのサブタイプ.
しかし、fruitsにデータを入れることはできません.もちろんFruitを取り出すことはできます.
汎用オブジェクトの参照を下に作成
fruitsがAppleを搭載したスーパークラス(supertype)のリストを指しているのを見た.同様に、スーパークラスとは何か分かりませんが、AppleとどのAppleのサブクラスもそのタイプと互換性があることを知っています.この未知のタイプがAppleであり、GreenAppleのスーパークラスである以上、私たちは書くことができます.
apples.add(new GreenApple);
apples.add(new Apple());
applesにapplesのスーパークラスを追加しようとすると、コンパイラは警告します.
apples.add(new Fruit());
apples.add(new Object());
ただし、オブジェクトを取り出す必要がある場合、取り出すのはObjectオブジェクトのみです.
アクセスの原則とPECSの法則
まとめ?extendsとthe?superワイルドカードの特徴は、以下の結論を得ることができます.データ型からデータを取得したい場合は、使用しますか?extendsワイルドカード オブジェクトをデータ構造に書き込む場合は、使用しますか?superワイルドカード 貯金したいし、取りたいならワイルドカードを使わないでください.
このPECSとは「Producer Extends,Consumer Super」のことです
参考書: The Java Tutorial Java Generics and Collections, by Maurice Naftalin and Philip Wadler Effective Java中国語版(第2版)、by Joshua Bloch.
Java汎用を理解する最も簡単な方法は、Javaタイプ変換(casting)の操作を節約する便利な文法と見なすことです.
List<Apple> apples=...
Apple apple=apples.get(1);
以上のようなコードは,プログラマが手動でタイプ判断を行う必要はないが,汎用型のため,コンパイラ段階でタイプをチェックした.
汎用的な構成
汎型の構成からタイプ変数の概念を引き出した.Java言語仕様では、タイプ変数は制限のないフラグであり、次のような状況で発生します.
public interface List<T> extends Collections<T>{
}
汎用メソッドとコンストラクタ
public static <T> getFirstItem(List<T> list){
}
汎用タイプのサブタイプ
このような3つの果物があるとします.
FujiApple,
Apple,
Fruit
FujiAppleはAppleのサブクラス、AppleはFruitのサブクラス、では
List
List
List
三者の関係は何ですか.
List<Apple> apples=new ArrayList<Apple>();
List<Fruit> fruits=apples;
上のコードは正しいですか?答えはコンパイルエラーです.
どうしてですか.次のコードを見てください
List<Apple> apples=new ArrayList<Apple>();
List<Fruit> fruits=apples;
fruits.add(new Strawberry());//Strawberry ,
AppleがFruitのサブタイプであれば、List
しかし、これは汎用型がタイプを決定するための公理に反している.これでリスト
タイプを判断しました.
したがって、List
ワイルドカード
汎用オブジェクトの参照を上に作成
List<Apple> apples=...
List<? extends Fruit> fruits=apples
上記のコードでは、2つの汎用オブジェクトに継承関係を持たせる場合は、ワイルドカードを使用します.
「?extends」は汎用タイプのサブタイプ相関が現実になった:AppleはFruitのサブタイプ、List
しかし、fruitsにデータを入れることはできません.もちろんFruitを取り出すことはできます.
汎用オブジェクトの参照を下に作成
List<Fruit> fruits=...
List<? super Apple> apples=fruits;
fruitsがAppleを搭載したスーパークラス(supertype)のリストを指しているのを見た.同様に、スーパークラスとは何か分かりませんが、AppleとどのAppleのサブクラスもそのタイプと互換性があることを知っています.この未知のタイプがAppleであり、GreenAppleのスーパークラスである以上、私たちは書くことができます.
apples.add(new GreenApple);
apples.add(new Apple());
applesにapplesのスーパークラスを追加しようとすると、コンパイラは警告します.
apples.add(new Fruit());
apples.add(new Object());
ただし、オブジェクトを取り出す必要がある場合、取り出すのはObjectオブジェクトのみです.
アクセスの原則とPECSの法則
まとめ?extendsとthe?superワイルドカードの特徴は、以下の結論を得ることができます.
このPECSとは「Producer Extends,Consumer Super」のことです
参考書: