2013-07-26 5 views
5

Предположим, что у меня есть это:Casting родовым подтипов общего класса

class Base<T> {} 

class Derived<T> extends Base<T> {} 

Тогда в моем коде, я могу смело отбрасывать без предупреждения, как это:

public <T> void foo(Base<T> base) { 
    Derived<T> f = (Derived<T>) base; // fine, no warning 
} 

, который прекрасно. Но если производный класс имеет больше параметров типа, он больше не работает:

class Base<T> {} 

class Derived<T, U> extends Base<T> {} 

public <T> void foo(Base<T> base) { 
    Derived<T, ?> f = (Derived<T, ?>) base; // unchecked warning! 
} 

Почему это? Есть ли что-то очевидное, что я здесь отсутствует?

+0

Почему это не работает? Это сработало для меня ... – m3th0dman

+0

Что не работает, так это то, что я получаю предупреждение, хотя это отличное исполнение. –

+0

Какой компилятор? Я вижу это с помощью компилятора Eclipse. –

ответ

5

Это кажется ошибкой для меня. От JLS §5.5.2. Checked Casts and Unchecked Casts:

отлитого из типа S к параметризованному типу (§4.5) Т снят , если не имеет по крайней мере одно из следующих условий:

  • S <: Т

  • Все аргументы типа (§4.5.1) Т неограниченные подстановочные

  • < T: S A й S не имеет подтипа X, кроме Т, где аргументы типа из X не содержатся в аргументах типа Т.

Учитывая ваши типы Base<T> и Derived<T, ?> в S и T соответственно, первые два условия явно не выполняются.

Это оставляет третье условие - которое не будет выполнено, если мы можем определить подтип Base<T>, кроме Derived<T, ?>, типа которого аргументы не содержится в аргументах типовых Derived<T, ?>. Если предупреждение правильное, такой подтип должен существовать, но я не могу его идентифицировать. Например, Derived<?, ?> не работает, потому что это не подтип Base<T>.

+0

Я не решался опубликовать этот ответ, потому что компилятор Eclipse имеет хорошую репутацию с дженериками, и, увидев это предупреждение в Eclipse, заставляет меня думать, что я чего-то не хватает. Если я неправильно читаю JLS, прокомментируйте или отредактируйте мой ответ для правильности. –

+1

JDK 7 не выдаёт предупреждение. JLS 5/6 не предоставила предупреждения. Я думаю, что компилятор jdt компилятора просто пропустил изменение или проигнорировал его из-за ошибки (он должен быть: «... нет подтипа X, кроме T, где ** | T | = | X | и ** ...» –

+0

@ BenSchulz Да, мне было интересно, что это формулировка - есть ли проблема JLS для этого? –

Смежные вопросы