Java Generics FAQ のこのエントリによると、ジェネリック メソッドに、ワイルドカード型を使用する同等の非ジェネリック メソッドがない場合があります。その答えによると、
メソッド シグネチャが複数レベルのワイルドカード タイプを使用する場合、ジェネリック メソッド シグネチャとそのワイルドカード バージョンの間には常に違いがあります。
彼らは、<T> void print1( List <Box<T>> list)
「同じタイプのボックスのリストを必要とする」メソッドの例を示しています。ワイルドカード バージョン はvoid print2( List <Box<?>> list)
、「さまざまな種類のボックスの異種リストを受け入れる」ため、同等ではありません。
次の 2 つのメソッド シグネチャの違いをどのように解釈しますか。
<T extends Iterable<?>> void f(Class<T> x) {}
void g(Class<? extends Iterable<?>> x) {}
直感的には、これらの定義は同等であるように思われます。ただし、呼び出しf(ArrayList.class)
は最初の方法を使用してg(ArrayList.class)
コンパイルされますが、2 番目の方法を使用した呼び出しはコンパイル時エラーになります。
g(java.lang.Class<? extends java.lang.Iterable<?>>) in Test
cannot be applied to (java.lang.Class<java.util.ArrayList>)
興味深いことに、次のようにコンパイルされるため、両方の関数を互いの引数で呼び出すことができます。
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;
この動作を説明するものは何ですか? これらのメソッドのシグネチャの違いをどのように解釈すればよいですか?