<Foo>
と<? extends Foo>
の違いについて誤解しているようです。私の理解から、もし
ArrayList<Foo> foos = new ArrayList<>();
これは、タイプFoo
のオブジェクトをこの配列リストに追加できることを示しています。 Foo
のサブクラスもFoo
型なので、次のようにエラーなしで追加できます。
ArrayList<Foo> foos = new ArrayList<>();
foos.add(new Foo());
foos.add(new Bar());
ここで、Bar extends Foo
。
ここで、foos
を次のように定義したとしましょう
ArrayList<? extends Foo> foos = new ArrayList<>();
私の現在の理解では、これはsome unknown type that extends Foo
を表すということです。これは、Foo
のサブクラスであるすべてのオブジェクトをこのリストに追加できることを意味します。つまり、ArrayList<Foo>
とArrayList<? extends Foo>
の間に違いはありません。
これをテストするために、私は次のコードを書いてみました
ArrayList<? extends Foo> subFoos = new ArrayList<>();
subFoos.add(new Foo());
subFoos.add(new Bar());
しかし、次のコンパイルエラーが表示されました
no suitable method found for add(Foo)
method Java.util.Collection.add(capture#1 of ? extends Foo) is not applicable
(argument mismatch; Foo cannot be converted to capture#1 of ? extends Foo)
no suitable method found for add(Bar)
method Java.util.Collection.add(capture#2 of ? extends Bar) is not applicable
(argument mismatch; Bar cannot be converted to capture#2 of ? extends Bar)
現在の理解に基づいて、<? extends Foo>
のリストにFoo
を追加できない理由がわかります。これは、それ自体のサブクラスではないためです。しかし、なぜBar
をリストに追加できないのか知りたいです。
私の理解のどこに穴がありますか?
あなたが自分で発見したように、ArrayList<? extends Foo> subFoos = new ArrayList<>();
として宣言されたArrayList
はあまり役に立ちません。
<? extends T>
の有用性を確認するには、次のことを考慮してください。
List<Foo> collect( List<? extends Foo> a1, List<? extends Foo> a2 )
{
List<Foo> collected = new ArrayList<>();
collected.addAll( a1 );
collected.addAll( a2 );
return collected;
}
これは後で次のように使用できます。
List<Foo> foos = collect( new ArrayList<Foo>(), new ArrayList<Bar>() );
または次のように:
List<Foo> foos = collect( new ArrayList<Bar>(), new ArrayList<Foo>() );
collect
メソッドが次のように宣言されている場合、上記のいずれも機能しないことに注意してください。
List<Foo> collect( List<Foo> a1, List<Foo> a2 )