我很清楚泛型類型在編譯時從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. 類中的值類型被存儲在哪裏?
- 4. 獲取泛型類型的類型列表裏面的Java
- 5. Java泛型類型
- 6. Java - 泛型類型
- 7. 文檔類型在哪裏?
- 8. Java通過泛型類型存儲條件
- 9. 泛型類型Java中
- 10. Java泛型類和非泛型類
- 11. Java類泛型
- 12. 接口的泛型類型在Java中
- 13. Java的泛型和類型
- 14. 的Java getMethod()泛型類型
- 15. Java的泛型類型
- 16. Scala中的存在類型的泛型
- 17. Java類的泛型
- 18. Java泛型:parametricise泛型類型
- 19. Java泛型:如何爲泛型類指定類類型?
- 20. 延長了泛型類型的類,JAVA
- 21. 在java中使用泛型類型
- 22. 在Java中編寫泛型類型
- 23. 捕獲泛型類型在Java中
- 24. 泛型類型的泛型?
- 25. Java泛型 - 類型聲明
- 26. Java泛型類型參數
- 27. Java泛型類型轉換
- 28. 比較泛型類型Java
- 29. Java泛型類型擦除
- 30. Java泛型 - 類型推斷