泛型擦除

本文深入探讨了Java泛型的实现机制,重点介绍了类型擦除的概念,即在编译期间,所有的泛型信息都会被替换为原始类型。编译器在类型检查后进行类型擦除,并在必要时生成桥方法以保持多态性。同时,由于类型擦除,Java编译器会在字节码中自动插入强制类型转换,使得在获取泛型对象时无需手动转换。此外,文章还提到了原始类型的确定规则,即如果类型变量有限制,原始类型将是第一个边界类型。
摘要由CSDN通过智能技术生成

1.Java泛型的实现方法:类型擦除

Java语言的泛型实现方式是擦拭法(Type Erasure)。
所谓擦拭法是指,虚拟机对泛型其实一无所知,所有的工作都是编译器做的。Java的泛型是由编译器在编译时实行的,编译器内部永远把所有类型T视为Object处理,但是,在需要转型的时候,编译器会根据T的类型自动为我们实行安全地强制转型。

Java 的泛型是伪泛型,因为在编译期间所有的泛型信息都会被擦除掉,泛型参数保留为原始类型。譬如 List 在运行时仅用一个 List 来表示(所以我们可以通过反射 add 方法来向 Integer 的泛型列表添加字符串,因为编译后都成了 Object),这样做的目的是为了和 Java 1.5 之前版本进行兼容。

泛型擦除具体来说就是在编译成字节码时首先进行类型检查,接着进行类型擦除(即所有类型参数都用他们的限定类型替换,包括类、变量和方法上的泛型参数,如果类型变量有限定则原始类型就用第一个边界的类型来替换,譬如
class Prd<T extends Comparable & Serializable> {} 的原始类型就是
Comparable),接着如果类型擦除和多态性发生冲突时就在子类中生成桥方法解决,接着如果调用泛型方法的返回类型被擦除则在调用该方法时插入强制类型转换。

2.类型擦除后保留的原始类型

原始类型 就是擦除去了泛型信息,最后在字节码中的类型变量的真正类型,类型变量擦除,并使用其限定类型(无限定的变量用Object)替换。
如果类型变量有限定,那么原始类型就用第一个边界的类型变量类替换。
比如: Pair这样声明的话

public class Pair<T extends Comparable> {}

那么原始类型就是Comparable。

3.自动类型检查

Java编译器是通过先检查代码中泛型的类型,然后再进行类型擦除,再进行编译。

4.自动类型强制转换

因为类型擦除的问题,所以所有的泛型类型变量最后都会被替换为原始类型。
既然都被替换为原始类型,那么为什么我们在获取的时候,不需要进行强制类型转换呢?
看下ArrayList.get()方法:

public E get(int index) {  
    RangeCheck(index);  
    return (E) elementData[index];  
}

可以看到,在return之前,会根据泛型变量进行强转。假设泛型类型变量为Date,虽然泛型信息会被擦除掉,但是会将(E) elementData[index],编译为(Date)elementData[index]。所以我们不用自己进行强转。当存取一个泛型域时也会自动插入强制类型转换。

自动地在结果字节码中插入强制类型转换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值