标签:++ family void leo i++ art 存储 string rgb
在上篇《Java泛型的基本使用》这篇文章中遗留下面问题,即将子类型也能加入到父类型的泛型中。要实现这样的功能必须借助于协变。
如今在上篇文章展示的Decorator类型的基础上,添加一些代码,如代码清单1所看到的。
代码清单1
/**
*
* 描 述:Exp2使用br/>
* 作 者:jiaan.gja<br/>
* 历 史: (版本号) 作者 时间 凝视 <br/>
* @param itemList
*/
public void doDecorate2(List<? extends T> itemList) {
for(int i = 0; i < itemList.size(); i++) {
System.out.println(itemList.get(i));
}
}
/**
*
* 描 述:Exp2使用<br/>
* 作 者:jiaan.gja<br/>
* 历 史: (版本号) 作者 时间 凝视 <br/>
* @param itemList
* @param t
*/
public void addDecorate2(List<? extends T> itemList, T t) {
// itemList.add(t);
}
能够看到这跟《Java泛型的基本使用》中的doDecorate和addDecorate方法差点儿一样,唯一的差别是将List<T>改为List<? extends T>,这样的语法被称为协变。假设你已经在IDE里写了上面的代码。肯定发现addDecorate2中的语句itemList.add(t);已经编译报错。所以我们先将itemList.add(t);这条语句临时凝视掉。先来看看doDecorate2有没有达到我们的预期。
如今我们尝试下协变的用途。即调用doDecorate2方法,如代码清单2所看到的。
代码清单2
/**
*
* 类 名: Exp2<br/>
* 描 述: 泛型的协变使用<br/>
* 作 者: jiaan.gja<br/>
* 创 建: 2015年8月20日<br/>
*
* 历 史: (版本号) 作者 时间 凝视
*/
class Exp2 {
public static void main(String[] args) {
Decorator<Auction> decoratorA = new Decorator<Auction>();
List<Auction> listA = new ArrayList<Auction>();
Auction auctionOne = new Auction("auctionOne");
Auction auctionTwo = new Auction("auctionTwo");
decoratorA.addDecorate2(listA, auctionOne);
decoratorA.addDecorate2(listA, auctionTwo);
decoratorA.doDecorate2(listA);
Decorator<Table> decoratorB = new Decorator<Table>();
List<Table> listB = new ArrayList<Table>();
Table tableOne = new Table("tableOne", 10);
Table tableTwo = new Table("tableTwo", 20);
decoratorB.addDecorate2(listB, tableOne);
decoratorB.addDecorate2(listB, tableTwo);
decoratorB.doDecorate2(listB);
Decorator<Service> decoratorC = new Decorator<Service>();
List<Service> listC = new ArrayList<Service>();
Service serviceOne = new Service("serviceOne", "methodOne");
Service serviceTwo = new Service("serviceTwo", "methodTwo");
decoratorC.addDecorate2(listC, serviceOne);
decoratorC.addDecorate2(listC, serviceTwo);
decoratorC.doDecorate2(listC);
/*
* 协变測试開始
*/
decoratorA.doDecorate2(listB);
decoratorA.doDecorate2(listC);
}
}首先。我们看到doDecorate2方法至少能达到《Java泛型的基本使用》中的doDecorate方法的效果。因为声明了decoratorA的类型是Decorator<Auction>,那么此时实例decoratorA的doDecorate2的參数能够觉得是以下这样:
List<? extends Auction> itemList
而listB的类型是ArrayList<Table>,listC的类型是ArrayList<Service>,也就是说协变同意:
List<? extends Auction> itemList = new ArrayList<Auction>(); List<? extends Auction> itemList = new ArrayList<Table>(); List<? extends Auction> itemList = new ArrayList<Service>();这说明itemList中既能够存储Auction。也能够存储Table和Service。
我们做个如果,当你想从itemList中获取Table的时候,Java编译器怀疑这实际可能是个Service。因此会有编译错误。如果想从itemList中获取Auction是没有问题的,由于不管是Table还是Service它们都能够被自己主动转换为父类Auction。这些猜測,能够通过代码清单3验证。
代码清单3
List<?相同的道理,当你想要向itemList中加入Table时,编译器怀疑itemList实际是个ArrayList<Service>,因此是不同意的。在获取Auction时是没有问题的,那么加入Auction会不会也能够?因为itemList可能是ArrayList<Service>或者ArrayList<Table>,依据上一篇《Java泛型的基本使用》的结论,这实际也是不能够的。能够用下列代码验证:extends Auction> itemList = listA; Auction a = itemList.get(0); Table t = itemList.get(0); Service s = itemList.get(0); itemList = listB; a = itemList.get(0); t = itemList.get(0); s = itemList.get(0); itemList = listC; a = itemList.get(0); t = itemList.get(0); s = itemList.get(0);
Auction auctionThree = new Auction("auctionThree");
itemList.add(auctionThree);
Auction tableThree = new Auction("tableThree");
itemList.add(tableThree);
Auction serviceThree = new Auction("serviceThree");
itemList.add(serviceThree);
因此这也说明了刚開始看到的addDecorate2中的语句itemList.add(t);为什么会编译报错。尽管如此,我们依旧希望能将子类型加入到父类型声明的泛型中。这该怎么办?Java当然也考虑到这个问题。请看下一篇《Java泛型的逆变》。
假设从泛型中获取子类,应该使用协变。
标签:++ family void leo i++ art 存储 string rgb
原文地址:http://www.cnblogs.com/gavanwanggw/p/7260630.html