这两天在对比着看《java编程思想》和《Effective JAVA》(第二版)中关于泛型的问题,对里面涉及到的一个泛型转换例子感觉很费解,如下:
interface UnaryFunction<T>{ T apply(T arg); } public class MyTestJob{>{ private
int i = 1; private static UnaryFunction<Object> ID_FUN = new
UnaryFunction<Object>() { @Overridepublic Object apply(Object arg) { return
arg; } };public static <T> UnaryFunction<T> identityFun(){ return
(UnaryFunction<T>) ID_FUN;//(1) } public static <T> List<T> test(){ return
(List<T>)new ArrayList<D>();//(2) } public static void main(String[] args){
String[] str = {"aaa","bbb","ccc"}; UnaryFunction<String> sameString =
identityFun();//(1) for(String s : str){ System.out
.println(sameString.apply(s)); } List<String> list = test();//(2) list.add(
"1234"); System.out.println(list.get(0)); } }
首先这段代码是能正常运行的,不过在函数内部会有转换警告;
如上述代码段标记(1)、(2)部分所示;
这个地方居然可以正常转换,而且能编译通过,我们都知道如下代码是不能编译通过的;
//B extends A List<A> lsta = new ArrayList<>(); List<B> lstb = new
ArrayList<>(); lsta = lstb;//编译不通过 因为泛型是不协变的,所以List<A>不是List<B>的父类,不能进行类型转换;
所以,对于上述(1)、(2)的类型转换很是疑惑,也没找到合理的解释,只能自己强行解释一波,如果有不妥的地方还请大家指正:
(1)对于(List<T>) new ArrayList<D>();这个转换能通过编译期检查,个人认为与List<?>相似,对于转换为泛型参数类型
非确定的类型在编译期执行边界类型检查,T的边界是Object类型,因此参考List<? extend Object> lst = new
ArrayList<Object>(),所以检查可以通过; (2)对于函数List<String> list =
test();这个调用的时候,由于泛型类型推导的原则,test函数中的T变为String类型,
编译期的类型检查这时只检查返回值的传递赋值这一步,并不在检测函数内部的类型转换,因此编译期检查通过; 而由于运行时类型擦除原因,函数能够正常运行。

“所以,在泛型中所有动作都发生在边界处——对传递进来的值进行额外的编译期检查,并插入对传递出去的值的转型”(泛型编译期的额外检查基本上发生在值得传递(赋值)过程中)。

技术
©2019-2020 Toolsou All rights reserved,
python中delete怎么用_python中如何使用np.delete()方法?大厂Java岗春招必看:论一个面渣逆袭之路上必学得那些知识点3 4j不是合法的python表达式_3+4j不是合法的Python表达式。SQL综合题 员工单位综合题pyqt按钮调用python程序_PyQt:链接按钮到程序中的函数找出游戏的获胜者(java)看完这个去面试,稳过~~将硬盘转换成GPT分区格式python常用内置函数C语言(猜数字小游戏)