美文网首页Java 杂谈
CoreJava笔记 - 范型程序设计(2)

CoreJava笔记 - 范型程序设计(2)

作者: 杀死BL | 来源:发表于2018-07-26 10:01 被阅读2次

范型代码和Java虚拟机

  1. 关键知识:类型擦除

    Java的范型是编译器层次的范型,而在Java虚拟机上并没有范型类。在程序中定义的范型类,都会被擦除类型变量,生成一个与限定类型绑定的raw type

    例如:<T>类型被擦除后,变为Object类,<T entends Comparable & Serializable>的类型被擦除后,变为第一个限定类Comparable接口。

    对于多个限定类型的范型定义,编译器会插入强制类型转换。因此tagging type的接口应该放在范型类型列表的最后。

  2. 范型表达式

    由于类型擦除,编译器在处理返回值时,会插入强制类型转换。

  3. 范型方法

    范型类Pair<T>包含方法setSecond(T newValue)。类型擦除后,虚拟机上只对应raw type方法setSecond(Object newValue)

    Pair的派生类DateInterval extends Pair<LocalDate>。这个类重载了setSecond(LocalDate)

    此时,在DateInterval中实际上有2个setSecond方法:

    • setSecond(LocalDate)
    • setSecond(Object)

    而范型类在继承的时候由于类型擦除,会引起多态失效。见下面的示例:

    DateInterval interval = new DateInterval(...);
    Pair<LocalDate> pair = interval;
    pair.setSecond(aDate)
    

    而实际运行中,Java虚拟机能够处理好这种多态。这是因为编译器会自动在DateInterval类中生成一个桥函数,重载了Pair中的setSecond(Object)

    class DateInterval extends Pair<LocalDate> {
        ...
        public void setSecond(LocalDate second) {...}
        ...
        public void setSecond(Object second) {
            setSecond((LocalDate)second);
        }
        ...
    }
    

    反之,DateInterval中的getSecond()也生成桥方法:

    public LocalDate getSecond() {
        return (Date) super.getSecond().clone();
    } 
    

    再总结一下Java范型转换:

    • 虚拟机中没有范型,只有普通的类和方法
    • 所有的类型参数,都被替代为限定类型(默认为Object)
    • 编译器用桥方法来保持多态
    • 为了保持类型安全,必要时插入强制类型转换
  4. 调用遗留代码

    • 把范型类传入遗留代码:产生警告。
    • 把遗留数据赋给范型类型:产生警告。

    有警告就有警告吧,不会比没有范型的时候更糟,最大的问题就是执行时抛出一个异常。

相关文章

网友评论

    本文标题:CoreJava笔记 - 范型程序设计(2)

    本文链接:https://www.haomeiwen.com/subject/cbvvmftx.html