Ogólna metoda z parametrami a nie generyczna metoda z symbolami wieloznacznymi

Wedługten wpis w FAQ Java Generics, istnieją pewne okoliczności, w których ogólna metoda nie ma równoważnej nie generycznej metody, która używa typów wieloznacznych. Zgodnie z tą odpowiedzią

Jeśli podpis metody używa wielopoziomowych typów wieloznacznych, zawsze istnieje różnica między sygnaturą metody ogólnej a jej wersją wieloznaczną.

Podają przykład metody<T> void print1( List <Box<T>> list), który „wymaga listy pudeł tego samego typu”. Wersja wieloznaczna,void print2( List <Box<?>> list), „akceptuje heterogeniczną listę skrzynek różnych typów”, a zatem nie jest równoważny.

Jak interpretujesz różnice między dwoma następującymi podpisami metod:

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

Intuicyjnie wydaje się, że te definicje powinny być równoważne. Jednak połączenief(ArrayList.class) kompiluje za pomocą pierwszej metody, ale wywołanieg(ArrayList.class) użycie drugiej metody powoduje błąd podczas kompilacji:

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

Co ciekawe, obie funkcje można nazwać argumentami innych, ponieważ następujące kompilują:

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

Za pomocąjavap -verbose Test, Rozumiemf() ma ogólny podpis

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

ig() ma ogólny podpis

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

Co wyjaśnia to zachowanie? Jak mam interpretować różnice między podpisami tych metod?

questionAnswers(4)

yourAnswerToTheQuestion