java泛型协变_Java泛型的协变
在上篇《Java泛型的基本使⽤》这篇⽂章中遗留下⾯问题,即将⼦类型也能加⼊到⽗类型的泛型中。要实现这样的功能必须借助于协变。
实验准备
如今在上篇⽂什么躬尽什么
章展⽰的Decorator类型的基础上,添加⼀些代码,如代码清单1所看到的。
代码清单1
/**
*
* 描 述:Exp2使⽤br/>
* 作 者:jiaan.gja
* 历 史: (版本号) 作者 时间 凝视
* @param itemList
*/
publill命令
c void doDecorate2(List extends T> itemList) {
for(int i = 0; i < itemList.size(); i++) {
System.out.(i));
}
}
/**
*
* 描 述:Exp2使⽤
* 作 者:jiaan.gja
* 历 史: (版本号) 作者 时间 凝视
* @param itemList
* @红烧排骨面
param t
*/
public void addDecorate2(List extends T> itemList, T t) {
// itemList.add(t);
}
能够看到这跟红枣馒头
《Java泛型的基本使⽤》中的doDecorate和addDecorate⽅法差点⼉⼀样,唯⼀的差别是将List改为List
extends T>,这样的语法被称为协变。假设你已经在IDE⾥写了上⾯的代码。肯定发现addDecorate2中的语句itemList.add(t);已经编译报错。所以我们先将itemList.add(t);这条语句临时凝视掉。先来看看doDecorate2有没有达到我们的预期。
实验:泛型协变
如今我们尝试下协变的⽤途。即调⽤doDecorate2⽅法,如代码清单2所看到的。
代码清单2
*
* 类 名: Exp2
* 描 述: 泛型的协变使⽤
* 作 者: jiaan.gja
* 创 建: 2015年8⽉20⽇
*
* 历 史: (版本号) 作者 时间 凝视
*/
class Exp2 {
public static void main(String[] args) {
Decorator decoratorA = new Decorator();
List listA = new ArrayList();
Auction auctionOne = new Auction("auctionOne");
Auction auctionTwo = new Auction("auctionTwo"); decoratorA.addDecorate2(listA, auctionOne);
decoratorA.addDecorate2(listA, auctionTwo);
decoratorA.doDecorate2(listA);
Decorator
List
Table tableOne = new Table("tableOne", 10);
Table tableTwo = new Table("tableTwo", 20);
decoratorB.addDecorate2(listB, tableOne);
decoratorB.addDecorate2(listB, tableTwo);
decoratorB.doDecorate2(listB);
Decorator decoratorC = new Decorator();
List listC = new ArrayList();
Service rviceOne = new Service("rviceOne", "methodOne"); Service rviceTwo = new Service("rviceTwo", "methodTwo"); decoratorC.addDecorate2(listC, rviceOne);
decoratorC.addDecorate2(listC, rviceTwo);
decoratorC.doDecorate2(listC);
/*
* 协变測试開始
decoratorA.doDecorate2(listB);
decoratorA.doDecorate2(listC);
}
}⾸先。我们看到doDecorate2⽅法⾄少能世界杯什么时候开始
达到《Java泛型的基本使⽤》中的doDecorate⽅法的效果。
因为声明了decoratorA的类型是Decorator,那么此时实例decoratorA的doDecorate2的參数能够觉得是以下这样:List extends Auction> itemList
⽽listB的类型是ArrayList
List extends Auction> itemList = new ArrayList();
List extends Auction> itemList = new ArrayList
List extends Auction> itemList = new ArrayList();
这说明itemList中既能够存储Auction。也能够存储Table和Service。
我们做个如果,当你想从itemList中获取Table的时候,Java编译器怀疑这实际可能是个Service。因此会有编译错误。如谁能懂我
果想从itemList 中获取Auctio自我描述
n是没有问题的,由于不管是Table还是Service它们都
能够被⾃⼰主动转换为⽗类Auction。这些猜測,能够通过代码清单3验证。
代码清单3
List
extends Auction> itemList = listA;
Auction a = (0);
Table t = (0);
Service s = (0);
itemList = listB;
a = (0);
t = (0);
s = (0);
itemList = listC;
a = (0);
t = (0);
s = (0);相同的道理,当你想要向itemList中加⼊Table时,编译器怀疑itemList实际是个ArrayList,因此是不同意的。在获取Auction时是没有问题的,那么加⼊Auction会不会也能够?因为itemList可能是ArrayList或者ArrayList
itemList.add(auctionThree);
Auction tableThree = new Auction("tableThree");
itemList.add(tableThree);
Auction rviceThree = new Auction("rviceThree");
itemList.add(rviceThree);
因此这也说明了刚開始看到的addDecorate2中的语句itemList.add(t);为什么会编译报错。尽管如此,
我们依旧希望能将⼦类型加⼊到⽗类型声明的泛型中。这该怎么办?Java当然也考虑到这个问题。请看下⼀篇《Java泛型的逆变》。
总结
假设从泛型中获取⼦类,应该使⽤协变。