Java泛型类型擦除以及其局限性

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

Java的泛型是伪泛型,Java的泛型基本上都是在编译器这个层次上实现的,在生成的字节码中是不包含泛型中的类型信息的,使用泛型的时候加上类型参数,在编译器编译的时候会去掉,这个过程称为类型擦除。

如在代码中定义List和List等类型,在编译后都会变成List,JVM看到的只是List,而由泛型附加的类型信息对JVM是看不到的。Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法在运行时刻出现的类型转换异常的情况,类型擦除也是Java的泛型与C++模板机制实现方式之间的重要区别。
例子:

public class fanxing {
    public static void main(String[] args) throws Exception {
        ArrayList<String> list = new ArrayList<String>();
        list.add("abc");
        Class cla = list.getClass();
        Method method = cla.getMethod("add", Object.class);
        method.invoke(list,123);
        System.out.println(list);
    }
}

输出:

[abc, 123]

这里发现定义泛型为String类型,但是通过反射机制,可以将数字123插入list中,我们利用反射调用add方法的时候,可以存储数字。这说明了String泛型实例在编译之后被擦除了,只保留了原始类型

当我们打印list的时候会发现报错

public class fanxing {
    public static void main(String[] args) throws Exception {
        ArrayList<String> list = new ArrayList<String>();
        list.add("abc");
        Class cla = list.getClass();
        Method method = cla.getMethod("add", Object.class);
        method.invoke(list,123);
        System.out.println(list);

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}

输出

[abc, 123]
abc
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	at com.leetcode.testAPI.fanxing.main(fanxing.java:16)

发现这里打印日志的时候会报错,因为输出的list的泛型是String,123不能被打印出来。
原始类型
原始类型 就是擦除去了泛型信息,最后在字节码中的类型变量的真正类型,无论何时定义一个泛型,相应的原始类型都会被自动提供,类型变量擦除,并使用其限定类型(无限定的变量用Object)替换。

类型擦除局限性

1、不能使用instanceof
List<String> list = new ArrayList<>();
System.out.println(list instanceof ArrayList<String>);

类型擦除后String类型不存在了,所以不能使用instanceof判断

2、不能用基本类型实例化类型参数

不能用类型参数代替基本类型。因此, 没有 Pair, 只 有 Pair。 当然,其原因是类型擦除。擦除之后, Pair 类含有 Object 类型的域, 而 Object 不能存储 int值。

3、不能创建参数化类型的数组
4、泛型类的静态上下文中类型变量无效

不能在静态域或方法中引用类型变量

5、不能抛出或捕获泛型类的实例
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值