Универсальный метод с параметрами против неуниверсального метода с подстановочными знаками

В соответствии сэта запись в FAQ по Generics JavaЕсть некоторые обстоятельства, когда универсальный метод не имеет эквивалентного неуниверсального метода, который использует подстановочные типы. Согласно этому ответу,

If a method signature uses multi-level wildcard types then there is always a difference between the generic method signature and the wildcard version of it.

Они дают пример метода<T> void print1( List <Box<T>> list), для которого "требуется список блоков одного типа." Версия с подстановочными знаками,void print2( List <Box<?>> list)& quot; принимает разнородный список блоков разных типов & quot; и, следовательно, не эквивалентно.

Как вы интерпретируете различия между следующими двумя сигнатурами метода:

 <T extends Iterable<?>> void f(Class<T> x) {}
                         void g(Class<? extends Iterable<?>> x) {}

Интуитивно кажется, что эти определения должны быть эквивалентны. Тем не менее, вызовf(ArrayList.class) компилируется с использованием первого метода, но вызовg(ArrayList.class) использование второго метода приводит к ошибке времени компиляции:

g(java.lang.Class<? extends java.lang.Iterable<?>>) in Test
    cannot be applied to (java.lang.Class<java.util.ArrayList>)

Интересно, что обе функции можно вызывать друг с другом & apos; аргументы, потому что следующие компилирует:

class Test {
    <T extends Iterable<?>> void f(Class<T> x) {
        g(x);
    }
    void g(Class<? extends Iterable<?>> x) {
        f(x);
    }
}

С помощьюjavap -verbose Test, Я могу увидеть этоf() имеет общую подпись

<T::Ljava/lang/Iterable<*>;>(Ljava/lang/Class<TT;>;)V;

а такжеg() имеет общую подпись

(Ljava/lang/Class<+Ljava/lang/Iterable<*>;>;)V;

Чем объясняется такое поведение? Как я должен интерпретировать различия между этими методами? подписи?

Ответы на вопрос(4)

Ваш ответ на вопрос