Java 擦除-编译后的泛型类型信息

Java 擦除-编译后的泛型类型信息,java,generics,type-erasure,Java,Generics,Type Erasure,我在一本书中偶然发现了下面的内容- //Here, T is bound by Object by default. class Gen<T> { T ob; // here, T will be replaced by Object Gen(T o) { ob = o; } //Return ob. T getob() { return ob; } } 然而,我看到了这一点- public class G

我在一本书中偶然发现了下面的内容-

//Here, T is bound by Object by default.
class Gen<T> {
    T ob; // here, T will be replaced by Object

    Gen(T o) {
        ob = o;
    }

//Return ob.
    T getob() {
        return ob;
    }
}
然而,我看到了这一点-

public class GenStr<T extends java.lang.String> {
  T str;

  GenStr(T);
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: aload_1
       6: putfield      #2                  // Field str:Ljava/lang/String;
       9: return

  T getstr();
    Code:
       0: aload_0
       1: getfield      #2                  // Field str:Ljava/lang/String;
       4: areturn
}
公共类GenStr{
T-str;
GenStr(T);
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:aload_0
5:aload_1
6:putfield#2//fieldstr:Ljava/lang/String;
9:返回
T getstr();
代码:
0:aload_0
1:getfield#2//fieldstr:Ljava/lang/String;
4:轮到你了
}

class-Gen{
T-ob;
Gen(T);
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:aload_0
5:aload_1
6:putfield#2//fieldob:Ljava/lang/Object;
9:返回
T getob();
代码:
0:aload_0
1:getfield#2//fieldob:Ljava/lang/Object;
4:轮到你了
}
为什么
.class
文件仍然显示形式类型参数

为什么.class文件仍然显示形式类型参数

简单:所以

  • 在编译时,编译器可以读取这样的.class文件并理解相应的类是泛型的,并且可以在源代码中作为泛型使用
  • 在运行时,一些代码可以检查该类的泛型性质
类型擦除指的是,关于实例化的泛型类所使用的特定类型的信息不会被保留。但是这个类是泛型的信息需要在类文件中。如果编译器没有看到Gen.java,而只看到Gen.class,那么编译器怎么知道
Gen
是泛型的呢

关于类的类型信息仍然保留。不显示有关单个实例的类型信息

因此,您知道
Gen
有一个类级别的类型参数(概念上)称为
T

您不知道运行时
Gen
实例的
t
。您甚至无法从
getob
中确定它:这仅仅给出了类型的下限(例如,如果
getob
返回
字符串
t
可以是
字符串
字符序列
可序列化
对象
)。如果它返回
null
,那么
T
可以是任何东西


您可以针对没有源代码的类(只有编译的字节码)用Java编写代码。编译器需要有关此类类的泛型的信息,以便能够确保正确使用它们。

为什么
文件不显示泛型参数?泛型仅在运行时被擦除。
class Gen extends java.lang.Object{
    java.lang.Object ob;
    Gen(java.lang.Object);
    java.lang.Object getob();
}
class GenStr extends java.lang.Object{
    java.lang.String str;
    GenStr(java.lang.String);
    java.lang.String getstr();
}
public class GenStr<T extends java.lang.String> {
  T str;

  GenStr(T);
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: aload_1
       6: putfield      #2                  // Field str:Ljava/lang/String;
       9: return

  T getstr();
    Code:
       0: aload_0
       1: getfield      #2                  // Field str:Ljava/lang/String;
       4: areturn
}
class Gen<T> {
  T ob;

  Gen(T);
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: aload_1
       6: putfield      #2                  // Field ob:Ljava/lang/Object;
       9: return

  T getob();
    Code:
       0: aload_0
       1: getfield      #2                  // Field ob:Ljava/lang/Object;
       4: areturn
}