27.Android架构-泛型擦除机制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了27.Android架构-泛型擦除机制相关的知识,希望对你有一定的参考价值。

参考技术A Java的泛型是JDK5新引入的特性,为了向下兼容,虚拟机其实是不支持泛型,所以Java实现的是一种
伪泛型机制,也就是说Java在编译期擦除了所有的泛型信息,这样Java就不需要产生新的类型到字节码,
所有的泛型类型最终都是一种原始类型,在Java运行时根本就不存在泛型信息。

使用ASM ByteCode Viewer查看他的字节码

可以看到我们设置的泛型R,被擦除为Object了,这就是泛型擦除

他的bytecode为

可以看到我们限定了泛型的类型,那么他的bytecode是什么样的?

可以看到虽然我们在Plate2中只定义了一个set get方法,但是bytecode中却有两个,其中一个get set方法添加了synthetic bridge 表示这是一个桥接方法,作用是为了保持多态性,可以看到 CHECKCAST java/lang/Comparable ,检查类型是否为Comparable,如果是的话再去调用上边的 public set(Ljava/lang/Comparable;)V 方法。可以这样理解, set(Ljava/lang/Object;)V 是从Plate接口实现来的, set(Ljava/lang/Comparable;)V 是他本身的,因为限定了类型范围

上边我们是通过showbytecode的方式查看的字节码,但是如果你点开类生成的class文件,你会发现,泛型既然被擦除了为什么在class中仍然可以看到?其实这里看到的只是签名而已,还保留了定义的格式,这样对分析字节码有好处。你甚至可以通过javap -c Plate2.class反编译class,你会发现,R还是能被看到,我们要看bytecode,通过showbytecode的方式比较真实

比如没有ArrayList<int>,只有ArrayList<Integer>.当类型擦除后,ArrayList的原始类中的类型变量(T)替换成Object,但Object类型不能 存放int值

因为擦除后,ArrayList<String>只剩下原始类型,泛型信息String不存在了,所有没法使用instanceof

因为泛型类中的泛型参数的实例化是在定义泛型类型对象 (比如ArrayList<Integer>)的时候指定的,而静态成员是不需要使用对象来调用的,所有对象都没创建,如何确定这个泛型参数是什么

因为擦除后两个equals方法变成一样的了

因为类型不确定

因为数组是协变( 在某些情况下,即使某个对象不是数组的基类型,我们也可以把它赋值给数组元素。这种属性叫做协变(covariance) ),擦除后就没法满足数组协变的原则

以上是关于27.Android架构-泛型擦除机制的主要内容,如果未能解决你的问题,请参考以下文章

关于Java泛型的类型擦除机制问题求教

Java 之 泛型擦除

Java泛型擦除——以super关键字指定类型下限的在泛型擦除时会被擦成啥样的呢?

关于Java泛型机制无非就这7个问题

Java泛型擦除

Java 泛型使用上下边界通配符解决泛型擦除问题