java泛型——编译期类型检查的范围

这两天在对比着看《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>() {
        @Override
        public 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类型,
编译期的类型检查这时只检查返回值的传递赋值这一步,并不在检测函数内部的类型转换,因此编译期检查通过;
而由于运行时类型擦除原因,函数能够正常运行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值