通配符类型中,允许类型参数变化。比如,通配符类型:
Couple<? extends Singer>
表示任何泛型类型,它的类型参数是Singer
的子类,如Couple
,但不会是Couple
。
假如现在我们需要编写一个方法去打印一些东西:
public static void printCps(Couple<Rapper> cps) {
Rapper one = cp.getOne();
Rapper two = cp.getTwo();
System.out.println(one.getName() + " & " + two.getName() + " are cps.");
}
正如前面所讲到的,不能将Couple
传递给这个方法,这一点很受限制。解决的方案很简单,使用通配符类型:
public static void printCps(Couple< ? extends Singer> cps)
Couple
是Couple< ? extends Singer>
的子类型。
我们接下来来考虑另外一个问题,使用通配符会通过Couple< ? extends Singer>
的引用破坏Couple
吗?
Couple<Rapper> rapper = new Couple<>(rapper1, rapper2);
Couple<? extends Singer> singer = rapper;
player.setOne(reader);
这样可能会引起破坏,但是当我们调用setOne
的时候,如果调用的不是Singer
的子类Rapper
类的对象,而是其他Singer
子类的对象,就会出错。我们来看一下Couple
的方法:
? extends Singer getOne();
void setOne(? extends Singer);
这样就会看的很明显,因为如果我们去调用setOne()
方法,编译器之 可以知道是某个Singer
的子类型,而不能确定具体是什么类型,它拒绝传递任何特定的类型,因为 ? 不能用来匹配。但是使用getOne
就不存在这个问题,因为我们无需care它获取到的类型是什么,但一定是Singer
的子类。
通配符限定与类型变量限定非常相似,但是通配符类型还有一个附加的能力,即可以指定一个超类型限定:
? super Rapper
这个通配符限制为**Rapper
的所有父类,为什么要这么做呢?带有超类型限定的通配符的行为与子类型限定的通配符行为完全相反,可以为方法提供参数,但是却不能获取具体的值,即访问器是不安全的,而更改器方法是安全的**:
编译器无法知道setOne
方法的具体类型,因此调用这个方法时不能接收类型为Singer
或Object
的参数。只能传递Rapper
类型的对象,或者某个子类型(Reader
)对象。而且,如果调用getOne
,不能保证返回对象的类型。
总结一下:
带有超类型限定的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。