次のメソッド宣言は、
public void testMethod(ArrayList<T extends Animal> list)
と
public <T extends Animal> void testMethod(ArrayList<T> list)
同じ?
それらは、1 つの重要な点で同じではありません。最初のケースでは、ジェネリック パラメーターはクラスのスコープにバインドされ、メソッドを複数回呼び出しても変化しません。
2 番目のケースでは、ジェネリック パラメーターは、メソッドが呼び出される引数に依存し、個別の呼び出しごとに異なる場合があります。
したがって、このクラスを考えると:
public class MyClass<T extends Animal> {
public void handleList1(List<T> list) {
// implementation
}
public <U extends Animal> void handleList2(List<U> list) {
// implementation
}
}
次のようにインスタンス化します。
MyClass<Bear> test = new MyClass<Bear>();
handleList1
タイプのリストでのみ呼び出すことができますBear
。一方、次のように呼び出すことができますhandleList2
。
test.handleList2(new ArrayList<Tiger>);
test.handleList2(new ArrayList<Lion>);
test.handleList2(new ArrayList<Puma>);
そのためのジェネリック パラメータは、メソッドにも指定された引数によって決定されるためです。
違いは、前者はコンパイルしないのに対し、後者はコンパイルすることです。それはあなたが求めていたものですか?
次の違いを意味する場合:
public void testMethod (ArrayList <? extends Animal> list)
と
public <T extends Animal> void testMethod (ArrayList <T> list)
ArrayList
違いは、最初のケースでは要素の実際のタイプを参照できないのに対し、2 番目のケースでは参照できることです。
おそらく、次の 2 つのケースを検討すると、違いがより明確になります。
public void testMethod (
ArrayList <? extends Animal> l1,
ArrayList <? extends Animal> l2)
と
public <T extends Animal> void testMethod (
ArrayList <T> l1, ArrayList <T> l2)
最初のケースでは、最初の引数はArrayList
を拡張する型でAnimal
あり、2 番目の引数はを拡張する型Arraylist
または (おそらく他の) 型ですAnimal
。
2 番目のケースでは、両方の引数がextends と同じ型ArralList
のですAnimal
。