JAVA泛型——逆变

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

在上篇《java泛型——协变》这篇文章中遗留以下问题——协变不能解决将子类型添加到父类型的泛型列表中。本篇将用逆变来解决这个问题。

实验准备我们首先增加以下方法,见代码清单1所示。

代码清单1

/***

* 描 述:Exp3使用逆变<br/>

* 作 者:jiaan.gja<br/>

* 历 史: (版本) 作者 时间 注释 <br/>

*@paramitemList*/publicvoiddoDecorate3(List<?superT>itemList, T t) {for(inti = 0; i < itemList.size(); i++) {

System.out.PRintln(itemList.get(i));

}

}/***

* 描 述:Exp3使用逆变<br/>

* 作 者:jiaan.gja<br/>

* 历 史: (版本) 作者 时间 注释 <br/>

*@paramitemList*/publicvoidaddDecorate3(List<?superT>itemList, T t) {

itemList.add(t);

}

语法List<? super T>即为Java泛型的逆变,addDecorate3方法中的itemList.add(t)语句也没有协变出现的编译问题。

实验:泛型逆变现在我们尝试下逆变的用途,如代码清单2所示。

代码清单2

/***

* 类 名: Exp3<br/>

* 描 述: 泛型的逆变使用<br/>

* 作 者: 耿嘉安<br/>

* 创 建: 2015年8月25日<br/>

*

* 历 史: (版本) 作者 时间 注释*/classExp3 {publicstaticvoidmain(String[] args) {

Decorator<Auction> decoratorA =newDecorator<Auction>();

List<Auction> listA =newArrayList<Auction>();

Auction auctionOne=newAuction("auctionOne");

Auction auctionTwo=newAuction("auctionTwo");

decoratorA.addDecorate3(listA, auctionOne);

decoratorA.addDecorate3(listA, auctionTwo);

decoratorA.doDecorate3(listA);

Decorator<Table> decoratorB =newDecorator<Table>();

List<Table> listB =newArrayList<Table>();

Table tableOne=newTable("tableOne", 10);

Table tableTwo=newTable("tableTwo", 20);

decoratorB.addDecorate3(listB, tableOne);

decoratorB.addDecorate3(listB, tableTwo);

decoratorB.doDecorate3(listB);

Decorator<Service> decoratorC =newDecorator<Service>();

List<Service> listC =newArrayList<Service>();

Service serviceOne=newService("serviceOne", "methodOne");

Service serviceTwo=newService("serviceTwo", "methodTwo");

decoratorC.addDecorate3(listC, serviceOne);

decoratorC.addDecorate3(listC, serviceTwo);

decoratorC.doDecorate3(listC);/*** 测试逆变开始*/decoratorA.doDecorate3(listB);

decoratorA.doDecorate3(listC);

}

}

我们发现以下两条语句都会编译出错:

decoratorA.doDecorate3(listB);

decoratorA.doDecorate3(listC);

我们暂且将这个问题放一放,将它们暂时注释掉,增加代码清单3中的代码。

代码清单3

List<Object> listD =newArrayList<Object>();

decoratorA.doDecorate3(listD);

decoratorA.doDecorate3(listA);

decoratorA.doDecorate3(listB);

decoratorA.doDecorate3(listC);

decoratorB.doDecorate3(listD);

decoratorB.doDecorate3(listA);

decoratorB.doDecorate3(listB);

decoratorB.doDecorate3(listC);

decoratorC.doDecorate3(listD);

decoratorC.doDecorate3(listA);

decoratorC.doDecorate3(listC);

decoratorC.doDecorate3(listB);

代码清单3中,decoratorA.doDecorate3(listB);decoratorA.doDecorate3(listC);decoratorB.doDecorate3(listC);decoratorC.doDecorate3(listB);这四条语句编译错误,这说明如下声明是允许的:

List<?superAuction> itemList =newArrayList<Object>();

List<?superAuction> itemList =newArrayList<Auction>();

List<?superTable> itemList =newArrayList<Object>();

List<?superTable> itemList =newArrayList<Auction>();

List<?superTable> itemList =newArrayList<Table>();

List<?superService> itemList =newArrayList<Object>();

List<?superService> itemList =newArrayList<Auction>();

List<?superService> itemList =newArrayList<Service>();

而下面这样是不允许的:

List<?superAuction> itemList =newArrayList<Table>();

List<?superAuction> itemList =newArrayList<Service>();

List<?superTable> itemList =newArrayList<Service>();

List<?superService> itemList =newArrayList<Table>();

现在我们编写以下代码:

List<?superAuction> itemList =listA;

Object o= itemList.get(0);

Auction a= itemList.get(0);

Table t= itemList.get(0);

Service s= itemList.get(0);

itemList=listD;

o= itemList.get(0);

a= itemList.get(0);

t= itemList.get(0);

s= itemList.get(0);

上述代码中,除了从itemList获取Object的语句之外,都会编译出错,这是为什么?因为itemList有可能是一个ArrayList<Object>,所以转型为Auction是可能错误的。itemList可能是ArrayList<Object>或者ArrayList<Auction>,所以转型为Table或者Service必然是不对的。

最后我们增加以下代码:

itemList.add(newAuction("auctionThr"));

itemList.add(newService("serviceThr", "methodThr"));

itemList.add(newTable("tableThr", 10));

上述代码没有问题,因为不论itemList是ArrayList<Object>或者ArrayList<Auction>,向其中添加Auction、Table、Service都符合最初的原则。

假如向itemList添加Object是编译失败的,因为itemList可能是ArrayList<Auction>。

总结如果向泛型中添加子类,可以使用逆变来实现。如果要从泛型中获取子类,逆变有转型错误,此时应该使用协变。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航