2016-09-03 9 views
24

아시다시피 Java에서 제네릭의 주요 목적 중 하나는 컴파일 타임 형식 안전을 제공하는 것입니다. 컴파일되면 코드는 문제없이 실행됩니다.문자열이 컴파일 오류없이 목록에 할당 됨

다음 코드가 컴파일되는 이유는 무엇입니까?

public static void main(String[] args) { 
    String s = getList(); 
} 

private static <T extends List> T getList() { 
    return (T)new ArrayList(); 
} 

잘 컴파일됩니다. 내 형식 안전한 컴파일은 어디에 있습니까? getList() 메서드는 String 클래스와 공통점이 없습니다.

+1

아니요. 원시가 아닌 유형을 사용하는 경우에도 컴파일됩니다. –

+0

@MarkusFischer, 나는 또한 그것에 대해 생각했지만 컴파일러는 String이 최종 클래스이고 어떤 서브 클래스도 가질 수 없다는 것을 깨닫습니다. – Andrew

+1

@ MarkusFischer,이 주석을 대답으로 변환해야합니다. 나는 이것이 바로 여기서 관찰 된 문제라고 생각합니다. 필자가 말했듯이 컴파일러는 문자열을 'final'로 간주하지 않으므로 컴파일시에 'MyClass extends String implements List'를 사용할 수 있습니다. – Zabuza

답변

13

이것은 유형 삭제 문제 자체가 아니라 거의 반대입니다. 시스템에서 실제 유형을 알고 있지만 런타임에는 문제가 발생합니다. 이 컴파일 이유는 List 인터페이스입니다. 컴파일러에 관한 한, String의 하위 클래스가 실제로 해당 인터페이스를 구현할 수 있으므로 컴파일러는 유효한 런타임 상황이 될 수 있으므로 StringList이 반환됩니다. 컴파일러는 String이 final로 간주하지 않으므로 실제로 List-String 클래스를 생성하는 것은 불가능합니다.

컴파일 과정에서 final을 고려하지 않은 이유에 대해서는 보헤미안의 질문에 대한 설명이 도움이됩니다.

+0

적어도 컴파일러 경고가 없어야합니까? javac 자체는 검사하지 않았지만 IDE는 검사되지 않은 캐스트와 원시 형식에 대해서는 경고하지 않습니다. 원시 타입이없고 경고가없는 곳에서는 타입이 명백하게 올바르지 않은 경우를 예로들 수 있습니다. – RudolphEst

+0

나는 컴파일러 경고가 좋을 것이고이 상황에 대해 이해할 것이라고 동의한다. 나는 javac이나 이클립스 중 하나도 보지 못했다. 다시 말하지만, 이것은 컴파일러가 조사하는 몇 개의 엣지 경우에 따라 달라지며, 분명히이 별자리를 확인하지 않기로 한 결정이 내려졌습니다. –