2013-08-07 3 views
26

마지막으로 제네릭 실험을 조금했습니다. 나는이 코드 조각 해낸 :Java : 제네릭 실험

public class Test { 

    static <T> void f(T x) { 
     x = (T) (Integer) 1234; 
     System.out.println(x); 
    } 

    public static void main(String[] args) { 
     f("a"); 
     f(1); 
     f('a'); 
     f(1.5); 
     f(new LinkedList<String>()); 
     f(new HashMap<String, String>()); 
    } 
} 

나는 이것을 실행하고이 출력을 가지고 :

1234 
1234 
1234 
1234 
1234 
1234 

예외없이를! 그게 어떻게 가능해?

+0

"왜 제네릭은 C++ 템플릿처럼 작동하지 않습니까?"라는 질문에 위험 할 정도로 조심해야합니다. –

답변

36

이것은 type erasure입니다. (많은 점이이 용어에 대해 google로 작성되었습니다.)

static void f(Object x) { 
    x = (Object) (Integer) 1234; 
    System.out.println(x); 
} 

그래서 System.out.println은 객체 xtoString 메소드를 호출 - 귀하의 경우는 Integer.toString()입니다 : 바이트 코드에 f를 컴파일 한 후 방법은 다음과 같이 나타납니다.

+1

thats 멋진 답변 :) –

3

유형 삭제 때문에. Oracle's documentation에서 :

제네릭 컴파일 타임에 엄격한 유형 검사를 제공하고 일반적인 프로그래밍을 지원하는 자바 언어로 소개되었다. 유형 매개 변수를 억제 할 경우 자신의 경계 또는 객체와 제네릭 형식의 모든 유형 매개 변수를 교체

  • : 제네릭을 구현하기 위해, 자바 컴파일러에 형의 삭제를 적용합니다. 따라서 생성 된 바이트 코드 에는 일반 클래스, 인터페이스 및 메서드 만 포함됩니다.

  • 유형 안전을 유지하기 위해 필요한 경우 삽입하십시오.

  • 확장 된 제네릭 형식에서 다형성을 보존하기 위해 브리지 메서드를 생성합니다.

유형 삭제는 매개 변수화 된 유형에 대해 새로운 클래스가 작성되지 않도록합니다. 결과적으로 제네릭은 런타임 오버 헤드를 발생시키지 않습니다.

+3

외부 리소스의 단어를 복사 할 때 항상 올바르게 말을하고 원래 단어를 연결하십시오. –