详解Java 中泛型的实现原理

时间:2021-05-19

泛型是 Java 开发中常用的技术,了解泛型的几种形式和实现泛型的基本原理,有助于写出更优质的代码。本文总结了 Java 泛型的三种形式以及泛型实现原理。

泛型

泛型的本质是对类型进行参数化,在代码逻辑不关注具体的数据类型时使用。例如:实现一个通用的排序算法,此时关注的是算法本身,而非排序的对象的类型。

泛型方法

如下定义了一个泛型方法, 声明了一个类型变量,它可以应用于参数,返回值,和方法内的代码逻辑。

class GenericMethod{ public <T> T[] sort(T[] elements){ return elements; }}

泛型类

与泛型方法类似,泛型类也需要声明类型变量,只不过位置放在了类名后面,作用的范围包括了当前中的成员变量类型,方法参数类型,方法返回类型,以及方法内的代码中。

子类继承泛型类时或者实例化泛型类的对象时,需要指定具体的参数类型或者声明一个参数变量。如下,SubGenericClass 继承了泛型类 GenericClass,其中类型变量 ID 的值为 Integer,同时子类声明了另一个类型变量 E,并将E 填入了父类声明的 T 中。

class GenericClass<ID, T>{ }class SubGenericClass<T> extends GenericClass<Integer, T>{ }

泛型接口

泛型接口与泛型类类似,也需要在接口名后面声明类型变量,作用于接口中的抽象方法返回类型和参数类型。子类在实现泛型接口时需要填入具体的数据类型或者填入子类声明的类型变量。

interface GenericInterface<T> { T append(T seg);}

泛型的基本原理

泛型本质是将数据类型参数化,它通过擦除的方式来实现。声明了泛型的 .java 源代码,在编译生成 .class 文件之后,泛型相关的信息就消失了。可以认为,源代码中泛型相关的信息,就是提供给编译器用的。泛型信息对 Java 编译器可以见,对 Java 虚拟机不可见。

Java 编译器通过如下方式实现擦除:

  • 用 Object 或者界定类型替代泛型,产生的字节码中只包含了原始的类,接口和方法;
  • 在恰当的位置插入强制转换代码来确保类型安全;
  • 在继承了泛型类或接口的类中插入桥接方法来保留多态性。

Java 官方文档原文

Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
Insert type casts if necessary to preserve type safety.
Generate bridge methods to preserve polymorphism in extended generic types.

下面通过具体代码来说明 Java 中的类型擦除。

实验原理:先用 javac 将 .java 文件编译成 .class 文件,再使用反编译工具 jad 将 .class 文件反编成回 Java 代码,反编译出来的 Java 代码内容反映的即为 .class 文件中的信息。

如下源代码,定义 User 类,实现了 Comparable 接口,类型参数填入 User,实现 compareTo 方法。

class User implements Comparable<User> { String name; public int compareTo(User other){ return this.name.compareTo(other.name); }}

JDK 中 Comparable 接口源码内容如下:

package java.lang;public interface Comparable<T>{ int compareTo(T o);}

我们首先反编译它的接口,Comparable 接口的字节码文件,可以在 $JRE_HOME/lib/rt.jar 中找到,将它复制到某个目录。使用 jad.exe(需要另外安装)反编译这个 Comparable.class 文件。

$ jad Comparable.class

反编译出来的内容放在 Comparable.jad 文件中,文件内容如下:

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.// Jad home page: http:///questions/25040837/generics-bridge-method-on-polymorphism

以上就是详解Java 中泛型的实现原理的详细内容,更多关于Java 泛型实现原理的资料请关注其它相关文章!

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章