关于泛型类及普通类中通配符的使用
通配符是为了在接受泛型类参数时提高可接受的参数范围:
例如方法
void setList(List<Number> list)
使用中传入参数
setList(new ArrayList<Number>());
是可以正常使用的,但是
setList(new ArrayList<Integer>());
则会报出类型转换错误,究其原因泛型的继承关系跟泛型类无关,如果想要使用第二种方式则需要使用通配符
void setList(List<? extends Number> list)
则上述两种传参都可以正常使用
关于通配符中extends与super的区别则是extends限定传入泛型类型只能为Number或Number的子类,相反super则是限定为Number或者Number的父类,所以在extends条件下
setList(new ArrayList<Object>());
是不被允许的,由此可以衍生出含有通配符的泛型类的使用限制
三个类的继承方式如下
class A{}
class B extends A{}
class C extends B{}
现在有一个含有通配符的list
List<? extends B> listB = new ArrayList<>();
listB.add(new A());//Error: add (capture<? extends B>) in List cannot be apply to A
listB.add(new B());//Error: add (capture<? extends B>) in List cannot be apply to B
listB.add(new C());//Error: add (capture<? extends B>) in List cannot be apply to C
add方法中任何的参数都无法被正确转换
B b = listB.get(0);
但是get方法可以正确获得泛型类型,同理
List<? super B> listB = new ArrayList<>();
listB.add(new A());//Error: add (capture<? extends B>) in List cannot be apply to A
listB.add(new B());
listB.add(new C());
Object object = listB.get(0);
传入参数类型可以是B或者B的子类,但是返回类型无法确定
在泛型类的传参中使用通配符另有差异
class T<E extends B>{
E e;
public void setlist(List<? extends E> list) {
list.add(new A());//Error: add (capture<? extends B>) in List cannot be apply to A
list.add(new B());//Error: add (capture<? extends B>) in List cannot be apply to B
list.add(new C());//Error: add (capture<? extends B>) in List cannot be apply to C
list.add(e);//Error: add (capture<? extends B>) in List cannot be apply to E
B b = list.get(0);
}
public void setlist2(List<? super E> list) {
list.add(new A());//Error: add (capture<? extends B>) in List cannot be apply to A
list.add(new B());//Error: add (capture<? extends B>) in List cannot be apply to B
list.add(new C());//Error: add (capture<? extends B>) in List cannot be apply to C
list.add(e);
Object object = list.get(0);
}
}
如果通配符是extends或者super泛型类型,则无论如何传参都无法被正确转换,只有泛型类型成员变量可以传入