前言

日常琐碎的时间下,不适合看一些长篇高质量的文章,但是琐碎时间也是时间,看一些短小精悍的文章来查缺补漏也是极好的。碎花化的时间,就交给“碎片化的文章”来填充吧。

今天“碎片化文章”主题:泛型-有限通配符。(推荐阅读5分钟+3分钟思考

正文

关于泛型:

上限通配符:<? extends Type>下限通配符:<? super Type>本文解决俩个问题:

1、无限通配符存在的问题2、上下限通配符的不同publicclassTypeTest{publicvoid test(){TypeTest.copy(newArrayList<Object>(),newArrayList<String>());TypeTest.copy(newArrayList<String>(),newArrayList<Object>());}publicstatic<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));}publicstaticvoid copy2(List<?> dest,List<?> src){for(int i=0; i<src.size(); i++) dest.set(i,src.get(i));}}

大家觉得这个TypeTest类有多少个错误?答案是俩个:

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,结束的很突然?没错就是这么突然,接下来的时间,大家可以关掉手机花个两三分钟想一想刚才的内容,想明白了,也就有收获了~

相关文章