在Java中演示协变和逆变?
请在Java中展示协变和逆变的一个好例子。
协方差:
class Super { Object getSomething(){} } class Sub extends Super { String getSomething() {} } Sub#getSomething是协变的,因为它返回Super#getSomething的返回types的子类(但是满足Super.getSomething()的约定)
逆变
 class Super{ void doSomething(String parameter) } class Sub extends Super{ void doSomething(Object parameter) } 
Sub#doSomething是逆变的,因为它需要Super#doSomething参数的一个超类的参数(但是,再次填满Super#doSomething的合同)
注意:这个例子在Java中不起作用。 Java编译器会重载并且不覆盖doSomething() – 方法。 其他语言也支持这种逆转的风格。
generics
对于generics也是可以的:
 List<String> aList... List<? extends Object> covariantList = aList; List<? super String> contravariantList = aList; 
你现在可以访问所有没有使用generics参数的方法(因为它必须是“extends Object”),但是getters会正常工作(因为返回的对象总是types为“Object”)
 对于contravariantList ,情况正好相反:你可以使用generics参数访问所有方法(你知道它必须是“String”的超类,所以你可以总是传递一个),但是没有getters(返回的types可能是任何其他的超types串) 
  协方差:Iterable和Iterator。 定义一个协变Iterable或Iterator几乎总是有意义的。 Iterator<? extends T>  Iterator<? extends T>可以像Iterator<T> – types参数出现的唯一地方是next方法的返回types,所以它可以安全地上传到T 但是如果你有S扩展T ,你也可以把Iterator<S>赋给Iterator<? extends T>types的variablesIterator<? extends T>  Iterator<? extends T> 。 例如,如果你正在定义一个查找方法: 
 boolean find(Iterable<Object> where, Object what) 
 你将不能用List<Integer>和5来调用它,所以最好定义为 
 boolean find(Iterable<?> where, Object what) 
  反差:比较器。 使用Comparator<? super T>几乎总是有意义的Comparator<? super T>  Comparator<? super T> ,因为它可以像Comparator<T> 。 types参数只作为compare方法参数types出现,所以T可以安全地传递给它。 例如,如果您有一个DateComparator implements Comparator<java.util.Date> { ... }并且想用该比较器对List<java.sql.Date>进行sorting( java.sql.Date是一个子类java.util.Date ),你可以这样做: 
 <T> void sort(List<T> what, Comparator<? super T> how) 
但不与
 <T> void sort(List<T> what, Comparator<T> how) 
看看Liskov替代原理 。 实际上,如果B类扩展了A类,那么只要需要A就可以使用B.