Java 类型擦除,泛型擦除后如何获取类型信息 简书

Java 类型擦除,泛型擦除后如何获取类型信息 简书,Java泛型的类型擦除示例详解

Java(泛型)的引入加强了参数类型的安全性,减少了类型的转换。但是需要注意的是,Java的泛型在编译器中是有效的,在运行时被删除,也就是说所有的泛型参数类型在编译后都会被清除。本文主要介绍Java泛型类型擦除的相关信息,有需要的可以参考一下。

目录

前言泛型的类型擦除原理如下:1擦除类定义中的类型参数1.1无限制类型擦除1.2受限类型擦除2擦除方法定义中的类型参数3多态性桥接方法和泛型的总结引用

前言

Java的特性是从JDK 1.5开始才添加的。因此,为了兼容之前的版本,Java泛型的实现采用了“伪泛型”的策略,即Java在语法上支持泛型,但在编译阶段会进行所谓的“类型擦除”,将所有的泛型表示(尖括号中的内容)替换为具体类型(其对应的原生态类型),就好像根本没有泛型一样。了解类型擦除对于用好泛型非常有帮助,尤其是一些看似“棘手”的问题。知道类型擦除将被解决。

泛型的类型擦除原则是:

消除类型参数声明,即删除它所包围的部分。

根据类型参数的上下限推断并替换所有类型参数为原生态类型:如果类型参数为无限制通配符或没有上下限,则用Object替换;如果有上下限,根据子类替换原则,取类型参数最左边的限制类型(即父类)。

为确保类型安全,必要时插入强制类型转换代码。

自动生成一个“桥接方法”,保证擦除类型后的代码仍然具有泛型“多态性”。

1 擦除类定义中的类型参数

1.1 无限制类型擦除

当类定义中对类型参数没有限制时,在类型擦除中直接用Object代替,即形如T和?的类型参数被替换为Object,请参见1。

图1:删除类定义中的类型参数

1.2 有限制类型擦除

当类定义中对类型参数有限制(上下限)时,就用类型擦除中类型参数的上下限来代替,比如TEXENDS数和?extends Number的类型参数替换为Number,超级编号被替换为对象,参见2。

图2:删除类定义中的受限类型参数

2 擦除方法定义中的类型参数

擦除方法定义中类型参数的原理与擦除类定义中的原理相同。这里,仅以erase方法定义中的有限类型参数为例,如图3所示。

图3:删除泛型方法中的类型参数

3 桥接方法和泛型的多态

考虑以下代码:

公共接口信息lt。Tgt{

//只返回var:-)

T info(T var);

}

公共类BridgeMethodTest实现InfoltIntegergt。{

@覆盖

公共整数信息(整数变量){

返回var

}

}

根据我们之前类型擦除的经验,擦除类型后的代码应该是这样的:

公共接口信息{

//只返回var

对象信息(对象变量);

}

公共类BridgeMethodTest实现信息{

@覆盖

公共整数信息(整数变量){

返回var

}

}

但很明显,这样擦除类型后的代码在语法上是错误的:虽然BridgeMethodTest类中有info方法,但与info接口要求覆盖的Info方法不一致:参数类型不一致。在这种情况下,Java编译器会自动添加一个所谓的“桥方法”来满足Java语法的要求,同时保证基于泛型的多态性能够有效。让我们反编译BridgeMethodTest.class文件,看看Java编译器是如何做到这一点的:

$ javap BridgeMethodTest.class

编译自“BridgeMethodTest.java”

公共类BridgeMethodTest实现Infojava.lang.Integer {

public BridgeMethodTest();

public Java . lang . integer info(Java . lang . integer);

public Java . lang . object info(Java . lang . object);

}

可以看到,Java编译器在BridgeMethodTest中自动添加了两个方法:默认的构造方法和带对象参数的info方法,带对象参数的info方法就是“桥方法”。如何理解“桥”这个词?让我们进一步反编译BridgeMethodTest,看看:

//由Jad v1.5.8e反编译,版权所有2001 Pavel Kouznetsov。

//Jad主页:http://www.geocities.com/kpdus/jad.html

//反编译器选项:packimports(3)

//源文件名:BridgeMethodTest.java

公共类BridgeMethodTest

实施信息

{

public BridgeMethodTest()

{

}

公共整数信息(整数整数)

{

返回整数;

}

公共可变对象信息(对象对象)

{

返回信息((整数)obj);

}

}

info(Object)方法通过调用子类的info(Integer)方法来桥接父类和子类,也就是说info(Object obj)方法起到了连接父类和子类的作用,使得Java的多态性在泛型的情况下仍然有效。

当然,在使用基于泛型的多态性时,我们不必过多考虑“桥接方法”,Java编译器会为我们处理好一切。

有关桥接方法的更多信息,请参考JLS的相关章节。

总结

这就是这篇关于Java泛型类型擦除的文章。有关Java泛型类型擦除的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望你以后能支持我们!

参考资料

http://docs . Oracle . com/javase/tutorial/Java/generics/index . html

http://docs . Oracle . com/javase/tutorial/extra/generics/index . html

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: