Java Generics(ワイルドカード)


109

Javaの一般的なワイルドカードについていくつか質問があります。

  1. 違いは何であるList<? extends T>とはList<? super T>

  2. バインドされたワイルドカードとは何ですか?


Ted Gaoの 回答が削除された場合(リンクのみだったため)、リンク先のブログ投稿は次とおりです。
royhowie 2015

回答:


123

あなたの最初の質問で<? extends T><? super T>は境界付きワイルドカードの例です。無制限のワイルドカードはのよう<?>に見え、基本的にはを意味し<? extends Object>ます。大まかに言うと、ジェネリックはどのタイプでもかまいません。バインドされたワイルドカード(<? extends T>または<? super T>)は、特定のタイプを拡張する必要ある(<? extends T>上限と呼ばれる)、または特定のタイプの祖先である必要がある(<? super T>下限と呼ばれる)ことで、タイプを制限します。

Javaチュートリアルの記事「ワイルドカード」と「ワイルドカードもっと楽しく」には、ジェネリックについてのかなり良い説明があります。


ちょうどそれを正しくするために、A <BおよびB <Cの場合、<A extends C>は間違っていますか?
Pablo Fernandez、

A <Bの場合、AがBを拡張することを意味し、AはCを拡張することを意味します。ただし、ワイルドカード構文ではそれを使用しないので、<?CはAまたはBのいずれかにあなたの選択肢を制限する>拡張
トカゲのビル

その場合、私が<?スーパーC>違いは何ですか?
Pablo Fernandez、

3
Java Genericsの別のリファレンスを推奨したかっただけです:angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
Zach Scrivena

3
@Pablo:<? super C>タイプがCタイプ階層の上の何かに制限されていることを意味します。(非常に遅い返信で申し訳ありません。コメント通知が2年前になかったと思いますか?)
Bill the Lizard

49

クラス階層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をコンパイルしないのはなぜですか?
VolkanGüven19年

38

Josh Blochは、いつ使用するかについての適切な説明superextends、このgoogle ioビデオトークで、彼がProducer extendsConsumersuperニーモニックについて言及しています。

プレゼンテーションスライドから:

一括メソッドを追加したいとします Stack<E>

void pushAll(Collection<? extends E> src);

– srcはEプロデューサーです

void popAll(Collection<? super E> dst);

– dstはEコンシューマーです


私はBlochの本を読みましたが、この特定のケースでは、extendsとsuperの違いはまだわかりません。
Pablo Fernandez、

ビデオを見て、私はそれはかなり明確だと思います。また、この「List <?extends T>とList <?super T>の違いは何ですか」について別の質問をする必要があると思います。(追加する場合は、ここからリンクを追加してください)
空欄

2
ベッド-完全にして独立させるために、この回答に例を含めないでください。リンクは短命です。
James Schek、2008年

3

型パラメーターに渡すことができる型の種類を制限したい場合があります。たとえば、数値を操作するメソッドは、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のスーパークラスのオブジェクトは受け入れない)のみを受け入れます。


1

一般に、

構造体にフォームのタイプの要素が含まれている場合、構造体から要素を? 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));
         }
    }

1

ジェネリックワイルドカードは、コレクションを操作するメソッドをより再利用可能にするために作成されます。

たとえば、メソッドにパラメータがある場合、このメソッドにList<A>のみ与えることができますList<A>。いくつかの状況下では、このメソッドの機能には無駄があります:

  1. このメソッドがからオブジェクトを読み取るだけの場合、このメソッドをList<A>許可する必要がありますList<A-sub>。(A-subはAであるため)
  2. このメソッドがにオブジェクトを挿入するだけの場合、このメソッドをList<A>許可する必要がありますList<A-super>。(AはAスーパーなので)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.