java泛型的逆变_Java泛型的逆变

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

实验准备

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

代码清单1

/***

* 描 述:Exp3使用逆变

* 作 者:jiaan.gja

* 历 史: (版本) 作者 时间 注释

*@paramitemList*/

public void doDecorate3(List super T>itemList, T t) {for(int i = 0; i < itemList.size(); i++) {

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

}

}/***

* 描 述:Exp3使用逆变

* 作 者:jiaan.gja

* 历 史: (版本) 作者 时间 注释

*@paramitemList*/

public void addDecorate3(List super T>itemList, T t) {

itemList.add(t);

}

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

实验:泛型逆变

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

代码清单2

/***

* 类 名: Exp3

* 描 述: 泛型的逆变使用

* 作 者: 耿嘉安

* 创 建: 2015年8月25日

*

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

classExp3 {public static voidmain(String[] args) {

Decorator decoratorA = new Decorator();

List listA = new ArrayList();

Auction auctionOne= new Auction("auctionOne");

Auction auctionTwo= new Auction("auctionTwo");

decoratorA.addDecorate3(listA, auctionOne);

decoratorA.addDecorate3(listA, auctionTwo);

decoratorA.doDecorate3(listA);

Decorator

List

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

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

decoratorB.addDecorate3(listB, tableOne);

decoratorB.addDecorate3(listB, tableTwo);

decoratorB.doDecorate3(listB);

Decorator decoratorC = new Decorator();

List listC = new ArrayList();

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

Service serviceTwo= new Service("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 listD = new ArrayList();

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 super Auction> itemList = new ArrayList();

List super Auction> itemList = new ArrayList();

List super Table> itemList = new ArrayList();

List super Table> itemList = new ArrayList();

List super Table> itemList = new ArrayList

List super Service> itemList = new ArrayList();

List super Service> itemList = new ArrayList();

List super Service> itemList = new ArrayList();

而下面这样是不允许的:

List super Auction> itemList = new ArrayList

List super Auction> itemList = new ArrayList();

List super Table> itemList = new ArrayList();

List super Service> itemList = new ArrayList

现在我们编写以下代码:

List super Auction> 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,所以转型为Auction是可能错误的。itemList可能是ArrayList或者ArrayList,所以转型为Table或者Service必然是不对的。

最后我们增加以下代码:

itemList.add(new Auction("auctionThr"));

itemList.add(new Service("serviceThr", "methodThr"));

itemList.add(new Table("tableThr", 10));

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

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

总结

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值