java泛型擦除

问题提出

List<String> 可以赋给 List<Integer> 吗,如果可以,如何实现?

泛型擦除

Java泛型是使用擦除来实现的,当使用泛型时,任何具体的类型信息都会被擦除。在泛型代码内部,无法获得任何有关泛型参数类型的信息。你唯一知道的就是你在使用一个对象。因此List<String>List<Integer> 在运行时实际上是相同的类型。这两种形式都被擦除成它们的“原生”类型 List。

此时我们来看下面代码中标注的几个地方,能正确编译运行吗?


public static void main(String[] args) {

        List<Integer> integerList = getStringList();  // 1
        System.out.println(integerList.get(0));  // 2
        System.out.println(integerList.get(0).toString());  // 3
        System.out.println(String.valueOf(integerList.get(0)));  // 4
    }


public static <T> List<T> getStringList(){
        List<String> result = new ArrayList<String>(){{
           add("1"); 
        }};
        return (List<T>)result;
    }

1、正确编译且能正常运行
由于泛型擦除,两个类型都被擦除为原生类型 List ,故而无异常。

2、正确编译且能正常运行

3、运行时异常,触发 java.lang.ClassCastException 异常
调用 integerList.get(0).toString() 方法时,实际上是泛型内部使用了隐式类型转换,调用了Integer.toString() 方法,但此时integerList.get(0) 实际存储的类型是String ,所以会触发类型转换异常。

4、正确编译且能正常运行
因为String.valueOf()方法使用了多态,实现了各种类型的支持,无论是Integer还是String 都有与之匹配的方法。

泛型边界

那么类似于 3 这种问题,有没有办法避免,或者说在编译器就使之暴露出来呢?当然有,那就是泛型边界。

边界可以在用于泛型的参数类型上设置限制条件。为此 java 泛型重用了 extends 关键字。

1、通配符

<?>  : 无界通配符,可以认为是一种装饰,因为使用无界通配符好像等价于使用原生类型 。
<? super T> :超类型通配符,限定下边界为 T (逆变)<? extends T> :限定上边界为 T (协变)。

2、举例
例如,我们可以将getStringList方法中的 T 限定为 T extends Integer 那么在编译时就会提升 cannot cast java.util.List<java.lang.String> to java.util.List<T>,因为上界为Integer,而显然String并不是 integer 的子类,所以无法转换。

public static <T extends Integer> List<T> getStringList(){
        List<String> result = new ArrayList<String>(){{
           add("1"); 
        }};
        return (List<T>)result; //无法转换,编译时报错
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值