java 泛型 协变_Java泛型的协变

在上篇《Java泛型的基本使用》这篇文章中遗留下面问题,即将子类型也能加入到父类型的泛型中。要实现这样的功能必须借助于协变。

实验准备

如今在上篇文章展示的Decorator类型的基础上,添加一些代码,如代码清单1所看到的。

代码清单1

/**

*

* 描 述:Exp2使用br/>

* 作 者:jiaan.gja

* 历 史: (版本号) 作者 时间 凝视

* @param itemList

*/

public void doDecorate2(List extends T> itemList) {

for(int i = 0; i < itemList.size(); i++) {

System.out.println(itemList.get(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 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,那么此时实例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中获取Auction是没有问题的,由于不管是Table还是Service它们都能够被自己主动转换为父类Auction。这些猜測,能够通过代码清单3验证。

代码清单3

List

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);相同的道理,当你想要向itemList中加入Table时,编译器怀疑itemList实际是个ArrayList,因此是不同意的。在获取Auction时是没有问题的,那么加入Auction会不会也能够?因为itemList可能是ArrayList或者ArrayList

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泛型的逆变》。

总结

假设从泛型中获取子类,应该使用协变。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值