Javagenerics(通配符)
在Java中我有几个关于通用通配符的问题:
- 
List<? extends T>什么区别List<? extends T>List<? extends T>和List<? super T>List<? super T>?
- 
什么是有界通配符,什么是无界通配符? 
 在你的第一个问题中, <? extends T>  <? extends T>和<? super T>  <? super T>是有界通配符的例子。 一个无界通配符看起来像<?> ,基本意思是<? extends Object>  <? extends Object> 。 它松散地表示generics可以是任何types。 一个有界的通配符( <? extends T>或<? super T> )通过说要扩展一个特定的types( <? extends T>被称为上界)来限制types,或者必须是特定types的祖先( <? super T>被称为下界)。 
Java教程对通配符和通配符 更有趣的文章有一些非常好的解释。
如果你有一个类层次结构A,B是A的一个子类,而C和D都是B的子类,如下所示
 class A {} class B extends A {} class C extends B {} class D extends B {} 
然后
 List<? extends A> la; la = new ArrayList<B>(); la = new ArrayList<C>(); la = new ArrayList<D>(); List<? super B> lb; lb = new ArrayList<A>(); //fine lb = new ArrayList<C>(); //will not compile public void someMethod(List<? extends B> lb) { B b = lb.get(0); // is fine lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B } public void otherMethod(List<? super B> lb) { B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A lb.add(new B()); // is fine, as we know that it will be a super type of A } 
 一个有界的通配符是? extends B  ? extends B ,其中B是某种types。 也就是说,这个types是未知的,但是可以在其上放置一个“绑定”。 在这种情况下,它是由一些类的边界,这是B的一个子类。 
 乔什布洛赫也有一个很好的解释,什么时候使用super和extends在这个谷歌iovideo谈话 ,他提到生产者extends消费者super助记符。 
从演示幻灯片:
假设你想把堆方法添加到
Stack<E>
void pushAll(Collection<? extends E> src);– src是一个E生产者
void popAll(Collection<? super E> dst);– dst是一个E消费者
有时您可能想要限制允许传递给types参数的types。 例如,对数字进行操作的方法可能只想接受Number或其子类的实例。 这是有界的types参数。
 Collection<? extends MyObject> 
意味着它可以接受与MyObject具有IS-关系的所有对象(即,任何对象是myObject的一种types,或者我们可以说任何MyObject的任何子类的任何对象)或MyObject类的对象。
例如:
 class MyObject {} class YourObject extends MyObject{} class OurObject extends MyObject{} 
然后,
 Collection<? extends MyObject> myObject; 
将仅接受MyObject或MyObject的子对象(即任何types为OurObject或YourObject或MyObject的对象,而不是MyObject的超类的任何对象)。
一般来说,
如果一个结构包含表单types的元素
? extends E? extends E,我们可以从结构中获得元素,但是我们不能将元素放入结构中
 List<Integer> ints = new ArrayList<Integer>(); ints.add(1); ints.add(2); List<? extends Number> nums = ints; nums.add(3.14); // compile-time error assert ints.toString().equals("[1, 2, 3.14]"); 
 为了将元素放入结构中,我们需要另一种名为Wildcards with super , 
  List<Object> objs = Arrays.<Object>asList(2, 3.14, "four"); List<Integer> ints = Arrays.asList(5, 6); Collections.copy(objs, ints); assert objs.toString().equals("[5, 6, four]"); public static <T> void copy(List<? super T> dst, List<? extends T> src) { for (int i = 0; i < src.size(); i++) { dst.set(i, src.get(i)); } } 
通用通配符的创build使得对Collection进行操作的方法更加可重用。
 例如,如果一个方法有一个List<A>参数,我们只能给List<A>这个方法。 在某些情况下,这种方法的function是浪费的: 
-  如果这个方法只从List<A>读取对象,那么我们应该允许List<A-sub>给这个方法。 (因为A-SUB是A)
-  如果这个方法只向List<A>插入对象,那么我们应该允许List<A-super>给这个方法。 (因为A是超A)