日常琐碎的时间下,不适合看一些长篇高质量的文章,但是琐碎时间也是时间,看一些短小精悍的文章来查缺补漏也是极好的。
碎花化的时间,就交给“碎片化的文章”来填充吧。
今天“碎片化文章”主题:泛型-有限通配符。
关于泛型:,无限通配符:的概念这里就不做累述,咱们直接主题:有限通配符。
- 上限通配符:<? 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));
}
}答案是俩个:

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圈子】获取资料,还有优质文章每日送达。