2009-06-02 2 views

답변

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.ObjectV extends java.lang.Object을 사용합니다. 형식 자체 (Map)도 클래스 java.lang.Object을 확장하며 인터페이스가 없습니다.

14

Java generics는 실제로 type erasure에 의해 구현되므로 바이트 코드에 유형 정보가 없습니다. 두 경우 모두

class NonGeneric { 
    List list; 
} 

그리고,

class Generic { 
    List<String> list; 
} 

: 예를 들어

,의이 모양에게 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#10List의 일반 유형이 String임을 나타내는 상수 풀에 있습니다.

(그리고 새로운 내가 Chris Jester-Young's answer에서 배운 지식 포함) 클래스 파일의 분해에 더 찾고

은 바로 Generic 클래스의 Code: block 전에 일정 # 10에 대한 참조가 :

:
java.util.List list; 
    Signature: length = 0x2 
    00 0A 

16 진수 값 0A 상수 풀 #10 지칭하는 십진수이다 10

따라서 정수 풀의 정보는 필드가 제네릭 형식임을 나타냅니다.

관련 문제