Параметр универсального типа Java не входит в его пределы

Готовясь к экзамену OCPJP 6 (именно поэтому я использую компилятор Java 1.6), я заметил кое-что неясное для меня относительно Java Generics. Рассмотрим следующий код:

class A<K extends Number> {

    public <V> V useMe1(A<? super V> a) { // OK
        return null;
    }

    public <V> V useMe2(A<? extends V> a) { // OK
        return null;
    } 

    public <V> V useMe3(A<V> a) { // ERROR, but why, since 2 above were ok
        return null;
    } 

}

Когда я пытаюсь скомпилировать код (с компилятором 1.6), я получаю ошибку:

параметр типа V находится за его пределами

Несмотря на непригодность приведенного выше кода, мне интересно, почему компилятор считает, что типы <? super V> а также <? extends V> соответствуют типу класса, но <V> нет (так как V совпадает с обеими границами).

Я не собираюсь изменять этот код, я хочу это понять. Код взят из примера экзаменационного вопроса OCPJP 6 с вопросом "Какая строка будет компилироваться?"

1 ответ

Третий, useMe3Сбой как V не гарантируется extend Number учитывая отсутствие границ на его декларации <V>, И так как аргумент объявлен как A<V> нет козла, V должен продлить Number и язык Java просит программиста явно заявить об этом в этом случае.

Это на самом деле легко, и, возможно, менее очевидно, почему другие два могут работать. Используя ? в их определении типа аргумента вы даете шанс того, что он будет совместим с extend Number даже когда V сам по себе является монастырем, не ограниченным какой-либо конкретной границей в отношении Number,

Вы должны заметить, что extend Number не влияет V дольше, но ? что бы это ни было. Еще один способ выразить это, есть неизвестный класс, который представлен этим ? и должен extend Number и вдобавок к этому для метода useMe1например, это должно быть супер V где V будет определяться кодом, который вызывает этот метод.

Это, возможно, более интересно в случае useMe2 где V может быть чем-то совершенно не связанным с Number, Например:

interface FooInterface { ... }
class MyNumber extends Number implements FooInterface { ... }

A<?> subject = ...;
A<MyNumber> param = ...; 
FooInterface foo = subject.useMe2(param);

в useMe2 позвони выше, V является FooInterface это не имеет ничего общего с Numberи ? в этом случае MyNumber, MyNumber ограничен A параметр типа, связанный с extends Number и определением параметра типа аргумента в useMe2 расширить FooInterface но V Сам по себе полностью неограничен.

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