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 チュートリアルのワイルドカードとワイルドカードをもっと楽しくする記事には、ジェネリックについてのかなり良い説明があります。
クラス階層 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 のサブクラスである何らかのクラスによって境界付けられます。
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 のスーパークラスのオブジェクトは受け入れません)。
Collection で動作するメソッドをより再利用しやすくするために、ジェネリック ワイルドカードが作成されます。
たとえば、メソッドにパラメーターがある場合、このメソッドにList<A>
のみ与えることができますList<A>
。状況によっては、このメソッドの機能には無駄です:</p>
List<A>
のみオブジェクトを読み取る場合は、このメソッドに渡すことが許可されている必要がありますList<A-sub>
。(AサブはAなので)List<A>
に渡せるようにする必要がありますList<A-super>
。(AはAスーパーなので)一般に、
構造体に form 型の要素が含まれている場合、構造体
? 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));
}
}