Подстановочный знак и тип границ pameter в Java

Рассмотрим этот случай:

class A {}

class B<T extends A, E extends T> {
    B<?, A> b;
    B<?, ? extends A> b2;
}

Как я понимаю границы типа, в этом случае эффективные верхние границы обоих T а также E является class A, Итак, вопрос: почему javac не принимает класс A в качестве аргумента в объявлении поля b, но принимает wildcard? extends A в объявлении поля b2?

3 ответа

Решение

Со следующими классами:

class A {}
class C extends A {}
class B<T extends A, E extends T> {}

Думайте об этом так:

E extends T extends A
С B<?,A> затем T -> ? а также E -> A
A extends ? extends A
Где ? может быть любой подкласс Aскажем C,
A extends C extends A явно недействительным.
Вот почему это ошибка компиляции.


Примечание для пользователей Eclipse:

Компилятор Eclipse 4.9.0 не согласился с javac 8u и Intellij и не выдал ошибку компиляции для общих аргументов в B<?,A>, Я предполагаю, что это ошибка в компиляторе Eclipse, но я не обращался к JLS, чтобы подтвердить это.

class B<T extends A, E extends T> {
    B<?, A> b; // <-- Eclipse does NOT emit a compile error
    B<?, ? extends A> b2;
}

Об этой предполагаемой ошибке сообщалось здесь.

Ваша декларация неверна. Вы упускаете точку "подстановочных знаков". Они используются для объявления неизвестного свойства. За B<?, E> b E должен продлить T и T должен продлить A но вы сказали, что первый общий тип ? что неизвестно! Итак, вы сказали, что неизвестный параметр должен быть расширен T так что A, Это неверно.

Отношения, которые вы создали, похожи E -> T -> A, После этого вы объявили 1. универсальный тип ? -> E -> T -> A и 2. универсальный тип как A -> E -> T -> ?, Так? должен распространяться? и A должен расширять E против. Это сбивает с толку и неизвестно для компилятора...

В вашей декларации поля b, тип T может быть что угодно A, В очереди E должен продлить T Однако вы предоставляете тип A за T, A не будет подклассом чего-то, что является подклассом A,

Другие вопросы по тегам