Javaの一般的なワイルドカードについていくつか質問があります。
違いは何である
List<? extends T>
とはList<? super T>
?バインドされたワイルドカードとは何ですか?
Javaの一般的なワイルドカードについていくつか質問があります。
違いは何であるList<? extends T>
とはList<? super T>
?
バインドされたワイルドカードとは何ですか?
回答:
あなたの最初の質問で<? extends T>
、<? super T>
は境界付きワイルドカードの例です。無制限のワイルドカードはのよう<?>
に見え、基本的にはを意味し<? extends Object>
ます。大まかに言うと、ジェネリックはどのタイプでもかまいません。バインドされたワイルドカード(<? extends T>
または<? super T>
)は、特定のタイプを拡張する必要がある(<? extends T>
上限と呼ばれる)、または特定のタイプの祖先である必要がある(<? super T>
下限と呼ばれる)ことで、タイプを制限します。
Javaチュートリアルの記事「ワイルドカード」と「ワイルドカードでもっと楽しく」には、ジェネリックについてのかなり良い説明があります。
<? super C>
タイプがC
タイプ階層の上の何かに制限されていることを意味します。(非常に遅い返信で申し訳ありません。コメント通知が2年前になかったと思いますか?)
クラス階層Aがある場合、BはAのサブクラスであり、CとDは両方とも以下のようにBのサブクラスです。
class A {}
class B extends A {}
class C extends B {}
class D extends B {}
その後
List<? extends A> la;
la = new ArrayList<B>();
la = new ArrayList<C>();
la = new ArrayList<D>();
List<? super B> lb;
lb = new ArrayList<A>(); //fine
lb = new ArrayList<C>(); //will not compile
public void someMethod(List<? extends B> lb) {
B b = lb.get(0); // is fine
lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
}
public void otherMethod(List<? super B> lb) {
B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
lb.add(new B()); // is fine, as we know that it will be a super type of A
}
境界付きワイルドカードは? extends B
、Bが何らかのタイプであるようなものです。つまり、タイプは不明ですが、「境界」を置くことができます。この場合、それはBのサブクラスであるいくつかのクラスによって制限されます。
List<? super B>
として説明一覧は、クラスBの親クラスであるタイプを受け入れますか?CとDがhmmをコンパイルしないのはなぜですか?
Josh Blochは、いつ使用するかについての適切な説明super
とextends
、このgoogle ioビデオトークで、彼がProducer extends
Consumersuper
ニーモニックについて言及しています。
プレゼンテーションスライドから:
一括メソッドを追加したいとします
Stack<E>
void pushAll(Collection<? extends E> src);
– srcはEプロデューサーです
void popAll(Collection<? super E> dst);
– dstはEコンシューマーです
型パラメーターに渡すことができる型の種類を制限したい場合があります。たとえば、数値を操作するメソッドは、Numberまたはそのサブクラスのインスタンスのみを受け入れたい場合があります。これが、境界型パラメーターの目的です。
Collection<? extends MyObject>
つまり、MyObjectとIS -Aの関係にあるすべてのオブジェクト(つまり、myObjectのタイプである任意のオブジェクト、またはMyObjectの任意のサブクラスの任意のオブジェクト)またはMyObjectクラスのオブジェクトを受け入れることができます。
例えば:
class MyObject {}
class YourObject extends MyObject{}
class OurObject extends MyObject{}
そして、
Collection<? extends MyObject> myObject;
MyObjectまたはMyObjectの子(つまり、OurObject、YourObject、またはMyObjectのタイプのオブジェクトは受け入れ、MyObjectのスーパークラスのオブジェクトは受け入れない)のみを受け入れます。
一般に、
構造体にフォームのタイプの要素が含まれている場合、構造体から要素を
? extends E
取得できますが、構造体に要素を配置できません
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]");
要素を構造に入れるには、と呼ばれる別の種類のワイルドカードが必要ですWildcards with super
。
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
ジェネリックワイルドカードは、コレクションを操作するメソッドをより再利用可能にするために作成されます。
たとえば、メソッドにパラメータがある場合、このメソッドにList<A>
のみ与えることができますList<A>
。いくつかの状況下では、このメソッドの機能には無駄があります:
List<A>
許可する必要がありますList<A-sub>
。(A-subはAであるため)List<A>
許可する必要がありますList<A-super>
。(AはAスーパーなので)