List<? extends Number> foo3 = new ArrayList<Number>(); // Number "extends" Number (in this context)List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends NumberList<? extends Number> foo3 = new ArrayList<Double>(); // Double extends Number
List<? super Integer> foo3 = new ArrayList<Integer>(); // Integer is a "superclass" of Integer (in this context)List<? super Integer> foo3 = new ArrayList<Number>(); // Number is a superclass of IntegerList<? super Integer> foo3 = new ArrayList<Object>(); // Object is a superclass of Integer
public class Collections {public static <T> void copy(List<? super T> dest, List<? extends T> src) {for (int i = 0; i < src.size(); i++)dest.set(i, src.get(i));}}
1) new ArrayList<C2>(): can store C2 D1 D2 E1 E2 E3 E42) new ArrayList<D1>(): can store D1 E1 E23) new ArrayList<D2>(): can store D2 E3 E44) new ArrayList<E1>(): can store E15) new ArrayList<E2>(): can store E26) new ArrayList<E3>(): can store E37) new ArrayList<E4>(): can store E4
对于每种可能的情况,我们都有一组“可存储”类型:这里以图形表示的7(红色)集合
正如你所看到的,没有一个安全类型是每个案例都通用的:
你不能list.add(new C2(){});,因为它可能是list = new ArrayList<D1>();
你不能list.add(new D1(){});,因为它可能是list = new ArrayList<D2>();
1) new ArrayList<A1>(): can store A1 B1 B2 C1 C2 D1 D2 E1 E2 E3 E42) new ArrayList<A2>(): can store A2 B2 C1 C2 D1 D2 E1 E2 E3 E43) new ArrayList<A3>(): can store A3 B3 C2 C3 D1 D2 E1 E2 E3 E44) new ArrayList<A4>(): can store A4 B3 B4 C2 C3 D1 D2 E1 E2 E3 E45) new ArrayList<B2>(): can store B2 C1 C2 D1 D2 E1 E2 E3 E46) new ArrayList<B3>(): can store B3 C2 C3 D1 D2 E1 E2 E3 E47) new ArrayList<C2>(): can store C2 D1 D2 E1 E2 E3 E4
public class Fruit{}
public class Melon extends Fruit{}
public class WaterMelon extends Melon{}
这里我们有
List<? extends Fruit> fruitExtendedList = …
//Says that I can be a list of any object as long as this object extends Fruit.
好的,现在让我们尝试从水果ExtendedList中获取一些值
Fruit fruit = fruitExtendedList.get(position)
//This is valid as it can only return Fruit or its subclass.
再试一次
Melon melon = fruitExtendedList.get(position)
//This is not valid because fruitExtendedList can be a list of Fruit only, it may not be//list of Melon or WaterMelon and in java we cannot assign sub class object to//super class object reference without explicitly casting it.
fruitExtendedList.add(new Fruit())
//This in not valid because as we know fruitExtendedList can be a list of any//object as long as this object extends Fruit. So what if it was the list of//WaterMelon or Melon you cannot add Fruit to the list of WaterMelon or Melon.
添加Melon对象
fruitExtendedList.add(new Melon())
//This would be valid if fruitExtendedList was the list of Fruit but it may//not be, as it can also be the list of WaterMelon object. So, we see an invalid//condition already.
最后让我们尝试添加WaterMelon对象
fruitExtendedList.add(new WaterMelon())
//Ok, we got it now we can finally write to fruitExtendedList as WaterMelon//can be added to the list of Fruit or Melon as any superclass reference can point//to its subclass object.
等等如果有人决定制作一种新型的柠檬,让我们说为了争论,SaltyLemon作为
public class SaltyLemon extends Lemon{}
现在水果扩展列表可以是水果,甜瓜,西瓜或盐柠檬列表。
那么我们的声明
fruitExtendedList.add(new WaterMelon())
也不是有效的。
基本上,我们可以说,我们不能写任何东西到一个水果ExtendedList。
总结List<? extends Fruit>
现在让我们看看
List<? super Melon> melonSuperList= …
//Says that I can be a list of anything as long as its object has super class of Melon.
现在让我们尝试从melonSuperList中获取一些价值
Fruit fruit = melonSuperList.get(position)
//This is not valid as melonSuperList can be a list of Object as in java all//the object extends from Object class. So, Object can be super class of Melon and//melonSuperList can be a list of Object type
同样,Melon、WaterMelon或任何其他对象都无法读取。
但请注意,我们可以读取Object类型的实例
Object myObject = melonSuperList.get(position)
//This is valid because Object cannot have any super class and above statement//can return only Fruit, Melon, WaterMelon or Object they all can be referenced by//Object type reference.
现在,让我们尝试从melonSuperList设置一些值。
添加对象类型对象
melonSuperList.add(new Object())
//This is not valid as melonSuperList can be a list of Fruit or Melon.//Note that Melon itself can be considered as super class of Melon.
添加水果类型对象
melonSuperList.add(new Fruit())
//This is also not valid as melonSuperList can be list of Melon
添加Melon类型对象
melonSuperList.add(new Melon())
//This is valid because melonSuperList can be list of Object, Fruit or Melon and in//this entire list we can add Melon type object.
添加WaterMelon类型对象
melonSuperList.add(new WaterMelon())
//This is also valid because of same reason as adding Melon
您可能会认为Integer extends Number和Integer会像<? extends Number>一样,但编译器会告诉您<? extends Number> cannot be converted to Integer(即,用人类的说法,任何扩展数字的东西都可以转换为整数是错误的):
class Holder<T> {T v;T get() { return v; }void set(T n) { v=n; }}class A {public static void main(String[]args) {Holder<? extends Number> he = new Holder();Holder<? super Number> hs = new Holder();
Integer i;Number n;Object o;
// Producer Super: always gives an error except// when consumer expects just Objecti = hs.get(); // <? super Number> cannot be converted to Integern = hs.get(); // <? super Number> cannot be converted to Number// <? super Number> cannot be converted to ... (but// there is no class between Number and Object)o = hs.get();
// Consumer Superhs.set(i);hs.set(n);hs.set(o); // Object cannot be converted to <? super Number>
// Producer Extendsi = he.get(); // <? extends Number> cannot be converted to Integern = he.get();o = he.get();
// Consumer Extends: always gives an errorhe.set(i); // Integer cannot be converted to <? extends Number>he.set(n); // Number cannot be converted to <? extends Number>he.set(o); // Object cannot be converted to <? extends Number>}}
List<? extends Number> list1 = new ArrayList<Integer>();list1.add(null); //OKNumber n = list1.get(0); //OKSerializable s = list1.get(0); //OKObject o = list1.get(0); //OK
list1.add(2.3); //ERRORlist1.add(5); //ERRORlist1.add(new Object()); //ERRORInteger i = list1.get(0); //ERROR
List<? super Number> list2 = new ArrayList<Number>();list2.add(null); //OKlist2.add(2.3); //OKlist2.add(5); //OKObject o = list2.get(0); //OK
list2.add(new Object()); //ERRORNumber n = list2.get(0); //ERRORSerializable s = list2.get(0); //ERRORInteger i = list2.get(0); //ERROR
Object.add(new T()); // compiles fine without errorObject.add(new U()); // compiles fine without errorObject.add(new V()); // compiles fine without error
Object.add(new S()); // errorObject.add(new O()); // error
但为什么上述两个错误?我们可以使用Object.add(new T());仅在以下情况下,
List<? super T> Object = new List<T>();List<? super T> Object = new List<S>();List<? super T> Object = new List<O>();
class A { }class B extends A { }class C extends B { }
List<? extends T>-读取和分配:
|-------------------------|-------------------|---------------------------------|| wildcard | get | assign ||-------------------------|-------------------|---------------------------------|| List<? extends C> | A B C | List<C> ||-------------------------|-------------------|---------------------------------|| List<? extends B> | A B | List<B> List<C> ||-------------------------|-------------------|---------------------------------|| List<? extends A> | A | List<A> List<B> List<C> ||-------------------------|-------------------|---------------------------------|
List<? super T>-编写和分配:
|-------------------------|-------------------|-------------------------------------------|| wildcard | add | assign ||-------------------------|-------------------|-------------------------------------------|| List<? super C> | C | List<Object> List<A> List<B> List<C> ||-------------------------|-------------------|-------------------------------------------|| List<? super B> | B C | List<Object> List<A> List<B> ||-------------------------|-------------------|-------------------------------------------|| List<? super A> | A B C | List<Object> List<A> ||-------------------------|-------------------|-------------------------------------------|