五分钟带你聊:泛型之有限通配符

653 阅读3分钟

日常琐碎的时间下,不适合看一些长篇高质量的文章,但是琐碎时间也是时间,看一些短小精悍的文章来查缺补漏也是极好的。

碎花化的时间,就交给“碎片化的文章”来填充吧。

今天“碎片化文章”主题:泛型-有限通配符。

关于泛型:,无限通配符:的概念这里就不做累述,咱们直接主题:有限通配符。

  • 上限通配符:<? extends Type>
  • 下限通配符:<? super Type>

本文解决俩个问题:

1、无限通配符存在的问题

2、上下限通配符的不同

大家觉得这个TypeTest类有多少个错误?

public class TypeTest {    
  public void test(){        
    TypeTest.copy(new ArrayList<Object>(),new ArrayList<String>());
    TypeTest.copy(new ArrayList<String>(),new ArrayList<Object>());
  }    
  public static <T> void copy(List<? super T> dest, List<? extends T> src) {  
    for (int i = 0; i < src.size(); i++)            
      dest.set(i, src.get(i));   
  }    
  public static void copy2(List<?> dest, List<?> src) {  
    for (int i=0; i<src.size(); i++)            
      dest.set(i,src.get(i));   
  }
}

答案是俩个:

file

1、无限通配符存在的问题

第一个错误很简单:对于 List<?>src来说,它的 get()可以取出任意类型(Object及其子类),毕竟它是无限通配符修饰。

对于 List<?>dest来说,它的 set()同样可以接受任意类型,“貌似”没有问题?

这里我们设想代码可以运行。对于dest和src来说,二者都是任意类型。

如果成功运行的代码, dest是ArrayList<String>, src是 ArrayList<Integer>,在运行期间通过 copy2()方法去拷贝 dest和 src。那么当dest尝试 get()时一定会崩溃!

因为 dest是按自己期望类型String取,但是 src可不是按 dest的期望类型去存,所以我们一定会在运行期间遇到:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

因此IDE一般会在代码编写阶段禁止这种问题的出现!

2、上下限通配符的不同

由于上边提到的“宽松的方法签名”(无限通配符),也就引出了有限通配符,也就是demo代码中 publicstatic<T>voidcopy(List<?superT>dest,List<?extendsT>src)里的实现。

这种写法就保证了上述的问题:

对于src来说,由于上限通配符的存在,只能 get()或 set()T及T的子类。

对于dest来说,由于下限通配符的存在,只能 get()或 set()T及T的父类。

在这个例子中,dest作为输出集合,get()方法只能得到T及T的父类,那么只要输入集合src提供的类型是T及T的子类,那么对于输出集合dest就一定没有问题。

这也就是demo代码中第2个错误出现的原因。

注意!这部分内容只是解释 <?superT>和 <?extendsT>的异同帮助大家理解有限通配符,在使用的时候还是要具体情况具体分析。

OK,结束的很突然?

没错就是这么突然,接下来的时间,大家可以关掉手机花个两三分钟想一想刚才的内容,想明白了,也就有收获了~

文源网络,仅供学习之用,如有侵权,联系删除。

我将面试题和答案都整理成了PDF文档,还有一套学习资料,涵盖Java虚拟机、spring框架、Java线程、数据结构、设计模式等等,但不仅限于此。

关注公众号【java圈子】获取资料,还有优质文章每日送达。