我很清楚泛型类型在编译时从Java代码中删除。什么信息(属性?)1.5+ JVM用于实现getGenericType
等?Java类文件中存储的泛型类型在哪里?
15
A
回答
29
它们存储在Signature
属性中;请参阅updated Java Virtual Machine Specification的第4.8.8节和字段类型签名格式的第4.4.4节。
下面是一个使用javap -verbose java.util.Map
一个例子:
public interface java.util.Map
SourceFile: "Map.java"
Signature: length = 0x2
00 1E
[other attributes omitted]
的Signature
属性在这里指定(如果你看这是大端,就像在JVM类文件格式的所有整数数量是)常量池值#30( 30 = 0x1E)。所以让我们看看那里:
const #30 = Asciz <K:Ljava/lang/Object;V:Ljava/lang/Object;>Ljava/lang/Object;;
在4.4.4中指定的语法的上下文中阅读此内容。所以,这使用了两个类型参数,K extends java.lang.Object
和V extends java.lang.Object
。类型本身(Map
)也延伸类java.lang.Object
,并且没有接口。
14
Java泛型确实由type erasure实现,所以在字节码中没有类型信息。
例如,让我们来看看它声明List
场,一个在通用和其他非通用的形式两类:
class NonGeneric {
List list;
}
而且,
class Generic {
List<String> list;
}
在这两种情况下, ,得到的字节码如下:
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
没有引用在ArrayList
或List
中使用的String
类型。所以,我们可以看到泛型确实是通过类型擦除来实现的。
但是,如果我们看一下常量池,我们可以找到差异。
非通用常量池:
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 //
通用常量池:
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参考:
java.util.List list;
Signature: length = 0x2
00 0A
十六进制值0A
是十进制10
,它指的是常量池#10
:
const #10 = Asciz Ljava/util/List<Ljava/lang/String;>;;
因此,来自常量池的信息用于表示字段是泛型类型。
相关问题
- 1. 您在哪里指定泛型类型?
- 2. 获取泛型类型的类型列表里面的Java
- 3. Java - 泛型类型
- 4. Java通过泛型类型存储条件
- 5. 文档类型在哪里?
- 6. 泛型类型Java中
- 7. Java类泛型
- 8. Java的泛型类型
- 9. Java类的泛型
- 10. 延长了泛型类型的类,JAVA
- 11. 在Java中编写泛型类型
- 12. Java泛型 - 类型推断
- 13. Java泛型 - 类型声明
- 14. Java泛型类型参数
- 15. Java:获得泛型类型
- 16. Java泛型和界类型
- 17. 如何在Java中获取类型变量的类型泛型
- 18. Java创建具有泛型类型的泛型类
- 19. TFS 2010中的工作项目类型; XML文件存储在哪里?
- 20. Java和泛型类
- 21. 存储泛型T类的C++向量
- 22. Java无类型泛型类,删除它们的功能泛型类型
- 23. toString()Java中的泛型类型
- 24. 泛型类型类
- 25. Java泛型 - 错误铸造泛型类
- 26. 在泛型类型
- 27. JAVA:泛型类继承和泛型类型继承
- 28. 如何使用泛型类型的泛型列表泛型类
- 29. 在Java中存储变量类型
- 30. 泛型类型