java中<? extends E>和<? super E> 的区别
import java.util.ArrayList;
public class Do1 {
/*
* Q:探究<? extends E>和<? super E>的使用和意义区别
* 通过预编译报错区别两者的使用区别
* */
public static void main(String[] args) {
/*
* <? extends person>使用时,person本身和他的子类(子类的子类)都没有报错
* */
ArrayList<? extends Person> al1 = new ArrayList<Person>();
ArrayList<? extends Person> al2 = new ArrayList<Man>();
ArrayList<? extends Person> al3 = new ArrayList<Woman>();
ArrayList<? extends Person> a14 = new ArrayList<ManBoy>();
/*
* <? super person>使用时,除了person本身没有报错外,其他都报错
* */
ArrayList<? super Person> b11 = new ArrayList<Person>();
ArrayList<? super Person> b12 = new ArrayList<Man>(); //报错
ArrayList<? super Person> b13 = new ArrayList<Woman>(); //报错
ArrayList<? super Person> b14 = new ArrayList<ManBoy>(); //报错
/*
* <? extends man>使用时,men本身和其子类没有报错,他的父类person和平行子类woman报错
* */
ArrayList<? extends Man> cl1 = new ArrayList<Person>(); //报错
ArrayList<? extends Man> cl2 = new ArrayList<Man>();
ArrayList<? extends Man> cl3 = new ArrayList<Woman>(); //报错
ArrayList<? extends Man> c12 = new ArrayList<ManBoy>();
/*
* <? super man>使用时,man本身和父类没有报错,子类menboy和平行子类woman报错
* */
ArrayList<? super Man> d11 = new ArrayList<Person>();
ArrayList<? super Man> d12 = new ArrayList<Man>();
ArrayList<? super Man> d13 = new ArrayList<Woman>(); //报错
ArrayList<? super Man> d14 = new ArrayList<ManBoy>(); //报错
//通过上面的例子可以判断出
//<? extends E>为泛型固定上界,当后面的实例类型是本身和子类(子类的子类)都是不会报错的
//<? super E>为泛型固定下界,当后面的实例类型是本身和其父类时不报错
/*
* 证明:通过<? extends woman>本身和子类不报错
**/
ArrayList<? extends Woman> el3 = new ArrayList<Woman>();
ArrayList<? extends Woman> e12 = new ArrayList<WomanGirl>();
/*
* 证明:通过<? super woman>本身和父类不报错
* */
ArrayList<? super Woman> f13 = new ArrayList<Person>();
ArrayList<? super Woman> f14 = new ArrayList<Woman>();
}
}
class Person{
}
class Man extends Person{
}
class ManBoy extends Man{
}
class Woman extends Person{
}
class WomanGirl extends Woman{
}
在上面的例子中,创建了Person类和子类Man类、Woman类。两个子类各自又扩展了两个子类。通过实例报错验证使用方法。
具体的使用意义的差别是
- <? extends E> 泛型固定上界接受本类和子类
- 在集合框架中,想要将子类集合的东西addAll()进父类集合中。父类集合名.addAll(子类集合名)
- 直接对父类集合经行扩容,将父类引用指向子类实例。此为父类引用指向子类的父类集合实现
- <? super E> 泛型固定下界——接受本类和父类
- 可双列集合(map)中,进行比较器(Comparator)的代码重用,提高效率
- 比较器(Comparator)使用父类类型编写,这样子类也可以向上转型使用。此为父类引用指向子类在比较器中的实现
补充:
java中的泛型一共有是三种
- ArrayList<T> al=new ArrayList<T>(); 指定集合元素只能是T类型
- ArrayList<?> al=new ArrayList<?>(); 集合元素可以是任意类型,这种没有意义,一般是方法中,只是为了说明用法
- 编译1:报错:ArrayList<? extends E> al=new ArrayList<? extends E>();
- 编译2:报错:ArrayList<?> al=new ArrayList<?>();
- 编译3:成功:ArrayList<?> al=new ArrayList<String>();
- 泛型的限定:
- <? extends E>:接收E类型或者E的子类型。
- <?super E>: 接收E类型或者E的父类型。