✅什么是类型擦除?

典型回答

类型擦除是Java在处理泛型的一种方式,如Java的编译器在编译以下代码时:

public class Foo<T> {
    T bar;
    void doSth(T param) {
    }
};

Foo<String> f1;
Foo<Integer> f2;

在编译后的字节码文件中,会把泛型的信息擦除掉:

public class Foo {
    Object bar;
    void doSth(Object param) {
    }
};

也就是说,在代码中的Foo 和 Foo使用的类,经过编译后都是同一个类。

所以说泛型技术实际上是Java语言的一颗语法糖,因为泛型经过编译器处理之后就被擦除了。

这种擦除的过程,被称之为——类型擦除。所以类型擦除指的是通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上。类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且在必要的时候添加类型检查和类型转换的方法。

类型擦除可以简单的理解为将泛型java代码转换为普通java代码,只不过编译器更直接点,将泛型java代码直接转换成普通java字节码。

扩展知识

C语言对泛型的支持

泛型是一种编程范式,在不同的语言和编译器中的实现和支持方式都不一样。

通常情况下,一个编译器处理泛型有多种方式,在C++中,当编译器对以下代码编译时:

template<typename T>
struct Foo
{
    T bar;
    void doSth(T param) {
    }
};

Foo<int> f1;
Foo<float> f2;

当编译器对其进行编译时,编译器发现要用到Foo和Foo,这时候就会为每一个泛型类新生成一份执行代码。相当于新创建了如下两个类:

struct FooInt
{
    int bar;
    void doSth(int param) {
    }
};

struct FooFloat
{
    float bar;
    void doSth(float param) {
    }
};

这种做法,用起来的时候很方便,只需要根据具体类型找到具体的的类和方法就行了。但是问题是,当我们多次使用不同类型的模板时,就会创建出来的很多新的类,就会导致代码膨胀。

原文: https://www.yuque.com/hollis666/xkm7k3/qcn00m