具体的な型
class Animal(){
}
class Dog extends Animal(){
}
DogはAnimalのサブクラスとします
new ArrayList extends Animal>とか
new ArrayList super Dog>などのワイルドカードオブジェクトを生成できません
ワイルドカード型はメソッドのパラメータ型に使います
List<Animal>とList<Dog>の関係
List<Animal>a=new ArrayList<>();
List<Dog>d=new ArrayList<>();
//===========================代入
a=d;//コンパイルエラー
d=a;//コンパイルエラー
//===========================メソッド呼び出し
//定義側
void func(List<Animal> p){
... pをList<Animal>として操作
}
//呼び出し側
func(animal);//有効
func(dog);//コンパイルエラー
オブジェクト代入は相互に不可能
メソッド呼び出しは、同じ型のみ可能
結論
Dog extends Animal だったとしてもList<Dog>とList<Array>に関係性はありません
List<? extends Animal>とList<Dog>の関係
List<Dog>d=new ArrayList<>();
//===========================代入
List<? extends Animal>ea;
ea=d;//有効
d=ea;//コンパイルエラー
//===========================メソッド呼び出し
//定義側
void func(List<?extends Animal> p){
... pをList<Animal>として操作
}
//呼び出し側
func(dog);//有効
func(animal);//有効
List<Dog>型はList<?extends Animal>に代入可能
List<Dog>型はfunc(List<?extends Animal>)のパラメータにできます
結論
List<Dog>型はList<?extends Animal>にアップキャスト可能
Dog extends Animal =>(ならば) List<Dog> extends List<? extends Array>と扱えます
上記 =>の両辺でDogとAnimalの位置関係が同じなので共変関係
List<? super Dog>とList<Animal>の関係
List<Animal>a=new ArrayList<>();
//===========================代入
List<? super Dog>sd;
sd=a;//有効
a=sd;//コンパイルエラー
//===========================メソッド呼び出し
//定義側
void func(List<? super Dog> p){
... funcはp.addするためのもの pはObject型として扱う
}
//呼び出し側
func(animal);//有効
List<Animal>型はList<?super Dog>に代入可能
List<Animal>型はfunc(List<?super Dog>)のパラメータにできます
結論
List<Animal>型はList<?super Dog>にアップキャスト可能
Dog extends Animal =>(ならば) List<Animal> extends List<? super Dog>と扱えます
上記 =>の両辺でDogとAnimalの位置関係が逆転しているため反変関係