一.通配符使用
一.?
通配符的主要作用就是让泛型能够接受未知类型的数据。
Ep:
publicclass GernericTest {
publicstaticvoid main(String[] args) throws Exception{
List<Integer> listInteger =new ArrayList<Integer>();
List<String> listString =new ArrayList<String>();
printCollection(listInteger);
printCollection(listString);
}
publicstaticvoid printCollection(Collection<Object> collection){
for(Object obj:collection){
System.out.println(obj);
}
}
}
结果报错,因为Integer和Object不兼容。(注:这里是容器内存储的类型,不能进行类型向上转换)
publicclass GernericTest {
publicstaticvoid main(String[] args) throws Exception{
List<Integer> listInteger =new ArrayList<Integer>();
List<String> listString =new ArrayList<String>();
printCollection(listInteger);
printCollection(listString);
}
publicstaticvoid printCollection(Collection<?> collection){
for(Object obj:collection){
System.out.println(obj);
}
}
}
修改后?代表着泛型,可以接受任意类型。
二.? extends ...
这个是上界通配符,举个例子
//Lev 1
class Food{}
//Lev 2
class Fruit extends Food{}
class Meat extends Food{}
//Lev 3
class Apple extends Fruit{}
class Banana extends Fruit{}
class Pork extends Meat{}
class Beef extends Meat{}
//Lev 4
class RedApple extends Apple{}
class GreenApple extends Apple{}
Set<?extends Fruit> set1=new Set<Apple>();
Set<?extends Fruit> set2=new Set<Food>();//error
所以上界通配符代表着该容器可以接受存储着该类(extends 后面那个)及其子类的容器
三.? super ...
下界通配符则与其刚好相反
Set<?super Fruit> set1=new Set<Apple>();//error
Set<?super Fruit> set2=new Set<Food>();
所以下界通配符代表着该容器可以接受存储着该类(extends 后面那个)及其父类的容器
二.PECS原则的含义
很多人对PECS含糊不清,这里根本原因是对上下界通配符理解不够。要注意,上下界通配符是对于容器而言的,而PECS是对于容器中的数据类型而言的。
PECS 的全英是producer extends consumer super,意思是生产者extends,消费者super。
对于 ?extends Fruit来说,里面存储的数据类型一定是Fruit及其子类,那么使用Fruit类的变量来接收set是一定可以的,反之,将Fruit及其子类例如Apple存入反而可能不成立,因为万一这个范类对应的是YanTaiApple那就是将父类存入子类中!
class Apple extends Fruit{}
class YanTaiApple extends Apple{}
Set<? extends Fruit> set1= new Set<YanTaiApple>(new YanTaiApple());
Fruit fruit=set1.get(0);
set1.add(new Apple());//error
下界通配符原理类似,对于? super Fruit来说,里面存储的类型一定都是Fruit及其父类,那么我们如果将Apple和Banana存入是可以的,但是从set取的话,我们不能确定哪种类型能够存储它(Object当然可以,但是这样没有意义,因为它的属性我们会失去)
class Fruit extends Food{}
class Apple extends Fruit{}
class Banana extends Fruit{}
Set<? super Fruit> set=new Set<Fruit>();
set.add(new Apple());
set.get(0);//error