2016-12-19 5 views
4

내가 매개 변수의 클래스 확보해야하는 일반적인 방법이에 .getClass()을 주조 : 그것은보기의 컴파일러의 타입 시스템의 관점에서 밝혀으로유형 매개 변수

public static<S> void doSomething(S inst) { 
    @SuppressWarnings("unchecked") 
    Class<? extends S> cls = (Class<? extends S>) inst.getClass(); 
    // do something with 'cls' and with 'inst'... 
} 

을, .getClass()Class<?>을 반환하고 Class<? extends S>으로 내려가며 은 확인되지 않음 dow-cast입니다.

내 질문은 다음과 같습니다. 어떤 상황에서이 다운 캐스트가 안전하지 않을 수 있습니까?

IIUC이 메서드에 대한 모든 호출 사이트는 정적 (컴파일 타임) 유형 S 인 inst 매개 변수의 값을 전달해야합니다. 값의 동적 (런타임) 유형 D는 S 또는 그의 서브 타입이다. 따라서 inst.getClass()는 DS의 하위 유형 인 경우 Class<? extends S>에 할당 할 수있는 Class<D> 객체를 반환합니다.

답변

1

어떤 상황이 다운 캐스트는 안전하지 않을 수 있습니까? |X| 표현식 inst의 컴파일시 타입의 소거이고

inst.getClass()의 리턴 타입은 Class<? extends |X|>이다. 여기서, |X|S의 삭제이며, 이는 Object입니다. 그것이 Class<?>이고 Class<? extends S>이 아닌 이유입니다.

소거가 필요한 이유는 S 잠재적 파라미터 화 된 형태 일 수 있지만 단지 구체화 유형 Class 객체 만 구체화 표현한다 종류로서 Class 유형 인수에 사용되어야한다. 예를 들어 을 얻는 것은 실제로 안전하지 않습니다.

Class<? extends ArrayList<String>>을 갖는 것이 안전하지 않은 이유는 무엇입니까? 예를 들어, .cast() 메서드를 사용하여 아무런 경고없이 무엇이든을 ArrayList<String>으로 전송할 수 있습니다. 그러나 .cast()과 같은 런타임 유형 검사는 구체화 된 유형 만 검사 할 수 있습니다 (Class 객체 자체는 구체화 된 유형을 나타냄). (런타임에 존재하지 않는) 형식 인수를 확인할 수 없습니다. 따라서 .cast()을 사용하면 경고없이 점검되지 않은 캐스트를 효과적으로 수행 할 수 있습니다.

1

도움이 될지 잘 모르겠습니다 만이 클래스 캐스트가 위험 할 수있는 상황의 예를 찾으려고했습니다.

public static <S> void doSomething(S inst, Consumer<S> newInstConsumer) throws IllegalAccessException, InstantiationException { 
    inst = (S) new Object();          // just a line of wrong code here 
    Class<? extends S> cls = (Class<? extends S>) inst.getClass(); // and if we don't check here 
    S newInstance = cls.newInstance(); 
    newInstConsumer.accept(newInstance);       // this code fails only here 
} 

@SuppressWarnings("unchecked") 
public static void main(String... args) throws InstantiationException, IllegalAccessException { 
    doSomething(new HelloWorldPrinter(), HelloWorldPrinter::print); 
} 
+0

흥미 롭습니다. 이것은 실제로 허점을 보여주지 만 최소한 하나 이상의 체크되지 않은 캐스트 (즉,'inst = (S) new Object')가 필요합니다. –