首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >泛型类型存储在java类文件中的什么地方?

泛型类型存储在java类文件中的什么地方?
EN

Stack Overflow用户
提问于 2009-06-02 04:48:21
回答 2查看 8.7K关注 0票数 17

我很清楚,泛型类型在编译时会从Java代码中删除。什么信息(属性?)1.5+ JVM是否用于实现getGenericType等?

EN

Stack Overflow用户

发布于 2009-06-02 05:13:20

Java泛型实际上是由type erasure实现的,所以字节码中没有类型信息。

例如,让我们看一下两个类,它们声明了一个List字段,一个是泛型的,另一个是非泛型的:

代码语言:javascript
复制
class NonGeneric {
    List list;
}

和,

代码语言:javascript
复制
class Generic {
    List<String> list;
}

在这两种情况下,结果字节码如下:

代码语言:javascript
复制
  Code:
   Stack=3, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   new #2; //class java/util/ArrayList
   8:   dup
   9:   invokespecial   #3; //Method java/util/ArrayList."<init>":()V
   12:  putfield    #4; //Field list:Ljava/util/List;
   15:  return

没有对ArrayListList中使用的String类型的引用。因此,我们可以看到泛型确实是通过类型擦除来实现的。

然而,如果我们看一下常量池,我们可以找到一个差异。

非泛型常量池:

代码语言:javascript
复制
  Constant pool:
const #1 = Method   #6.#15; //  java/lang/Object."<init>":()V
const #2 = class    #16;    //  java/util/ArrayList
const #3 = Method   #2.#15; //  java/util/ArrayList."<init>":()V
const #4 = Field    #5.#17; //  NonGeneric.list:Ljava/util/List;
const #5 = class    #18;    //  NonGeneric
const #6 = class    #19;    //  java/lang/Object
const #7 = Asciz    list;
const #8 = Asciz    Ljava/util/List;;
const #9 = Asciz    <init>;
const #10 = Asciz   ()V;
// snip the rest //

通用常量池:

代码语言:javascript
复制
  Constant pool:
const #1 = Method   #6.#17; //  java/lang/Object."<init>":()V
const #2 = class    #18;    //  java/util/ArrayList
const #3 = Method   #2.#17; //  java/util/ArrayList."<init>":()V
const #4 = Field    #5.#19; //  Generic.list:Ljava/util/List;
const #5 = class    #20;    //  Generic
const #6 = class    #21;    //  java/lang/Object
const #7 = Asciz    list;
const #8 = Asciz    Ljava/util/List;;
const #9 = Asciz    Signature;
const #10 = Asciz   Ljava/util/List<Ljava/lang/String;>;;
const #11 = Asciz   <init>;
const #12 = Asciz   ()V;
// snip the rest//

可以看到,在Generic类中,我们可以看到常量池中有两个额外的常量,#9#10,这表明List具有String的泛型类型。

(并结合我从Chris Jester-Young's answer学到的新知识)

进一步查看类文件的反汇编,在Generic类的Code: block之前有一个对常量#10的引用:

代码语言:javascript
复制
java.util.List list;
  Signature: length = 0x2
   00 0A 

十六进制值0A是以十进制表示的10,它引用常量池#10

代码语言:javascript
复制
const #10 = Asciz   Ljava/util/List<Ljava/lang/String;>;;

因此,使用常量池中的信息来指示字段是泛型类型。

票数 17
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/937933

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档