제네릭 코드는 중간 변수없이 컴파일에 실패

codebox :

나는 코드의 첫 번째 2 줄 것을 놀라게하고 main아래는 컴파일러에 의해 사용할 수 있습니다. 내가 그 말을 할 때 나를 신뢰하는 것 같다 getIt()를 반환 Dog서명도 허용에도 불구하고 Cat반환 할 수 있습니다.

public class GenericsAreWeird {
    public static void main(String... args){
        // This is fine
        Dog d = getIt();
        d.woof();

        // This fails to compile
        // getIt().woof();

        // This compiles but gives a runtime ClassCastException
        Cat c = getIt();
        c.meow();
    }

    private static <T extends Animal> T getIt(){
        return (T) new Dog();
    }

    public static class Animal {}

    public static class Cat extends Animal{
        public void meow(){}
    }

    public static class Dog extends Animal{
        public void woof(){}
    }
}

나는 일반적으로 자바 제네릭 그래서이 깨진 것 같다 허용하지 않습니다 일을 뭔가를 컴파일러 오류를주는 것이 아니라 런타임에 말해 의해 ClassCastExceptions과에서 저를 보호하기 위해 신뢰합니다.

그것은 또한 직관적 같다 :

Dog d = getIt();
d.woof();

정확히 해당되지 않습니다 :

getIt().woof();

컴파일러는 "힌트"로서 중간 변수를 필요로한다.

제네릭은 항상 이런 식으로 일을 했습니까? 수있는 사람 포인트 나에게 (또는 제공) 컴파일러는이 같은 클래스 관련 오류를 데리러 실패 다른 시나리오 괜찮은 설명?

luk2302 :

return (T) new Dog();대부분의 경우가 컴파일러를 알려줍니다 위해
"당신의 유형 검사와 함께 닥쳐, 나는 더 나은 당신보다 알고 Dog항상에 할당 될 것 T"
되는 컴파일러 응답이
"좋아, 그럼 당신은 더 나은 지금이 호출하지 돌봐 후 진행 방법은 그 밖에 아무것도 반환하기를 기대 / A Cat"

그럼 당신은 않습니다 그것은을 반환하는 기대를 호출 Cat하고 자격을 얻을 ClassCastException. 당신은 당신이 더 나은 (당신이하지 않는)을 알고 컴파일러에게 때문에 런타임 예외를 얻을.

추천

출처http://10.200.1.11:23101/article/api/json?id=477380&siteId=1