java通配符和List

在java泛型的使用过程中常常需要使用通配符,最常用的就是使用<?>这个无限定通配符。很多时候使用泛型时都不依赖于类型参数T中的方法,但如果使用object类的话又会受到很多限制,这时候就会用到<?>
比如说一下这个函数

public void printList(List<Object> list)
 { 
    for (Object e : list) 
    System.out.println(e + " "); 
   
 }

本来想打印任意的List,结果发现能够输入的只有List ,这是因为在java中泛型是不协变的,这确实导致了很多的麻烦,但是将代码改为List<?>后,就可以接受任意类型List。
前面说了泛型是不能协变的,所以为了实现协变,可以使用有限定的通配符。同样是打印List

public void printList(List<Resource> list)
 { 
    for (Resource e : list) 
    System.out.println(e + " "); 
   
 }

上面这个函数可以打印Resource类型List,但对于Resource子类型的List却无法打印,原因前面说了两遍了,泛型是不能协变的,但是将代码改为

public void printList(List<? extends Resource> list)
 { 
    for (Resource e : list) 
    System.out.println(e + " "); 
   
 }

就能解决这个问题。

另外还有一个可能使用的通配符是上限通配符 <? super A>,比如List<? super Cat> b = new ArrayList<>();不过有违直观印象的是,这个数组看上去能够存储的是Cat的父类型,b.add(new Animal());这个代码却是会出错的,反而b.add(new WhiteCat());这个才是对的,这是为什么呢,其实可以这样思考:因为你告诉编译器List中存储的是Cat父类型,但编译器却不知道要添加的是哪一个父类型,但当你添加的是Cat子类型的时候,由于你告诉编译器下界是Cat,所以不管输入什么子类型那么它一定都是一种Cat。再来看get方法就更能认清这一点,事实上只有Object o1 = b.get(0);能够编译通过,因为你告诉编译器下界是Cat,但上界是完全不确定的,所以用除了Object之外的任何类型来接受都可能会出问题。所以总结下来<? super A>能addA的子类型,get只能是Object类型。
相反的,有List<? extends Cat> animal,它所能add的只有null,因为你告诉编译器它能存储Cat的子类型,编译器却不知道要添加的是哪种子类型,就会报错。但是像Cat s1 = animals.get(0); Animal s2 = animals.get(0); 却是可以的,因为上界是Cat,所以返回值用Cat和Animal接收一定是可行的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值