通配符的定义
通配符是另外一种类型,其传入的为未知类型
通配符用?
表示,其具有上界而且具有下界,定义方式分别为
上界< ? extends Object>
不知道是什么类型但是肯定是Object的子类
下界< ? super Object>
不知道是什么类型但是肯定是Object的父类
上界也叫子类型限定(及他可以接受此类的所有继承类)
extends A 这个类型限定为此类的所有子类
下界也叫超类型限定(及他可以接受此类的基类和基类的基类等)
super A这个类型限定为A的所有超类(父类)直至Object。
下界
ArrayList<? super A> a = new ArrayList<>();
a.add(new C());
a.add(new B());
a.add(new A());
for (Object object : a) {
System.out.println(object.toString());
}
结果
time20180530.C@e61fd1
time20180530.B@331059
time20180530.A@766a24
可以看出当我将A设置为下界的时候
因为编译器知道我肯定会放进去A,或者A的子类,所以编译器可以让我add进去。
上界
ArrayList<? extends C> b = new ArrayList<>();
//编译出错
b.add(new C());
A a2 = b.get(1);
编译出错
因为
因为编译器不知道当前List所持有的类型因为其限定为上界C,而C若有多个子类,那么List到底是哪种类型,所以他拒绝我add,但是在get的时候,因为其get的所有子类都可以转换为C调用子类所具有的方法,所以编译器会返回一个C的对象。
总结
所以其实上界表示可以获取到返回值,但是不能设置参数。
下界可以设置参数,但是不能使用返回值
如果你想从一个数据类型里获取数据,使用 ? extends 通配符
如果你想设置参数,使用 ? super 通配符
如果即想存又想取,不能用通配符
A<? extends B> a = new A();
a.setA(null);
B a2 = a.getA();
A<? super B> b = new A();
b.setA(new B());
Object b1 = b.getA();