Со страницы 49 OCP Java SE 6 Programmer Practice Exams, вопрос 11. Нам дан такой код:
class A { }
class B extends A { }
class C extends B { }
public class Carpet<V extends B> {
public <X extends V> Carpet<? extends V> method(Carpet<? super X> e) {
// insert code here
}
}
И нас спрашивают: Что, независимо вставленное в отмеченную строку, будет компилироваться?
Итак, я тестирую первый ответ - return new Carpet<X>()
. Оно работает. Хорошо, мои рассуждения выглядят так: если у меня есть возвращаемый тип Carpet<? extends V>
, он должен возвращать что-то, что расширяет V
. Просто раньше написано, что X extends V
, так что отлично, X
работает.
Следующий ответ - return new Carpet<V>()
. Ну, это еще проще, потому что V
уже "расширяет" V
, так что я могу это вернуть. Работает, хорошо, хорошо.
Далее - return new Carpet<A>()
. Это не работает, компилятор кричит:
Type parameter 'A' is not within its bound; should extend 'B'
Но я согласен. Это написано рядом с объявлением класса, V extends B
. Итак, я понимаю, что могу вернуть что-то, что расширяет V
, что расширяет B
. Точно не A
.
Итак, я вижу следующий ответ - return new Carpet<B>()
. Уф, легко, компилятор только что сказал: «должен расширять B
, поэтому B
(как перед V
для «чего-то, что расширяет V
») должно быть просто идеальным. Но! Это не компиляция:
Error:(6, 16) java: incompatible types
required: Carpet<? extends V>
found: Carpet<B>
Я не понимаю, почему. Объяснение, данное в книге:
Недопустимо использовать конкретный тип класса, поскольку точная область действия V неизвестна.
Но, честно говоря, я до сих пор не понимаю. Я не уверен, что означает «точная область» в этом контексте, но компилятор сказал, что параметр возвращаемого типа должен расширять B
. Итак, он может понять (как и я), что «что-то, что расширяет V
», является «чем-то, что расширяет B
». Итак, почему B
не работает?
Не могли бы вы дать лучшее объяснение?