泛型(泛型擦除、泛型可以反射、泛型的限制和问题)
发布日期:2021-05-06 00:58:44 浏览次数:17 分类:技术文章

本文共 1638 字,大约阅读时间需要 5 分钟。

1. 泛型擦除

泛型的擦除是是用一种称为类型消除( type erasure)的方法来实现的。当泛型存在于编译时,一旦被确认安全使用时,就会将其转换为原生类型也就是擦除成原生类型。泛型擦除是指泛型代码在编译后,都会被擦除为原生类型。例如Zoo
和Zoo
,实际上在运行时都是同一种类型,即原生类型Zoo。这就意味着运行时,Java并不存在类型参数这一概念,因此将无法任何相关的参数类型信息。例如下面的代码证实了泛型擦除:
package Generic.wildcardsAndBoundaries;public class Test {
public static void main(String[] args) {
Zoo
fishZoo = new Zoo<>(new Fish()); Zoo
birdZoo = new Zoo<>(new Bird()); System.out.println("两者的类型相同吗? " + fishZoo.getClass().equals(birdZoo.getClass())); }}

运行结果:

在这里插入图片描述


1.1 为什么要擦除泛型

擦除是java泛型方法实现的一种折中办法。因为擦除的核心动机是使得泛化的代码可以使用非泛化的类库,反之亦然,为了让非泛型的代码和泛型的代码共存,实现擦除非常可靠!

1.2 如何擦除

其实擦除的实质就是将原有的类型参数替换成即非泛化的上界。如:
public class Computer
{
private E e; public Cmputer(E e){
this.e=e; } public E apply(){
return this.e; }}
上方代码经过编译后,将被编译成以下代码形式:
public class Computer {
private Object e; public Computer(Object e) {
this.e = e; } public Object apply() {
return e; }}
通过比较你会发现原有类型参数消失了,取而代之为参数类型Object,这是因为Computer
没有指明上界,编译器将其自动擦除成顶类Object类型若指明了上界如
,则会有如下翻译:

在这里插入图片描述


1.3 多边界擦除

在这里插入图片描述


2 泛型可以反射

在这里插入图片描述


3 泛型的限制和问题

因为擦除机制使得运行时丢失了泛型信息,因此一些理所当然的功能在java泛型系统中得不到支持。
  • 限制一:
    为了保证类型安全,不能使用泛型类型参数创建实例
    // 不合法 T object=new T() ;
  • 限制二:
    不能声明泛型实例数组,这会导致运行错误
    // 不合法 T[] numbers= new T[capcity];
    但可以通过创建一个Object类型数组然后将它的类型转换E[]来规避这个限制。
    T[] number= (E[])new Object[capcity]:
  • 限制三:
    在静态的环境下不允许参数类型是泛型类型的。(由于泛型类的所有实例都有相同的运行时类,所以泛型类的静态变量和方法是被它的所有实例所共享的。既然是共享的你就没有必要再重新定义一样的泛型类型,那如果你不定义一样的泛型类型,又达不到共享(或者说是一致性),更没有必要让这种情况通过。所以,在静态环境了类的参数被设置成泛型是非法的。)
  • 限制四:
    泛型类对象无法被抛出或捕获,因为泛型类不能继承或实现Throwable接口及其子类。

上一篇:Python--推导式与生成器推导式(化简代码,适合于创建或控制有规律的序列)
下一篇:Java--泛型(通配符、泛型边界、泛型与继承)

发表评论

最新留言

表示我来过!
[***.240.166.169]2025年03月23日 14时17分48秒