3
import java.util.List;
import java.util.ArrayList;

interface Canine {}
class Dog implements Canine {}
public class Collie extends Dog {
    public static void main(String[] args){
        List<Dog> d = new ArrayList<Dog>();
        List<Collie> c = new ArrayList<Collie>();
        d.add(new Collie());
        c.add(new Collie());
        do1(d); do1(c);
        do2(d); do2(c);
    }
    static void do1(List<? extends Dog> d2){
        d2.add(new Collie());
        System.out.print(d2.size());
    }
    static void do2(List<? super Collie> c2){
        c2.add(new Collie());
        System.out.print(c2.size());
    }
}

この質問に対する答えは、メソッドがワイルドカードの汎用typを使用する場合、コレクションにアクセスまたは変更できるが、両方はできないことを示しています。(キャシーとバート)

'メソッドがワイルドカードの汎用typを使用する場合、コレクションにアクセスまたは変更できますが、両方を使用することはできません'とはどういう意味ですか?

私の知る限り、メソッドdo1にはList<? extends Dog> d2、d2にのみアクセスでき、変更できないようになっています。メソッドd2にはList<? super Collie> c2、c2にアクセスして変更でき、コンパイルエラーがないようになっています。

一般的なガイドライン

4

5 に答える 5

2

どんな種類のリストか分からないので、 aCatに a を追加することはできません。List<? extends Animal>それもあるかもしれませんList<Dog>Catだからあなたはあなたをに投げたくありませんBlack Hole。そのためmodificationList宣言された方法は許可されていません。

同様に、 から何かをフェッチするときList<? super Animal>、そこから何が得られるかわかりません。Object、または を取得することもできますAnimalAnimalただし、この に安全に追加できますList

于 2012-10-15T11:28:18.943 に答える
1

コードを IDE に貼り付けました。内部で次のエラーが通知されましたdo1:

List 型のメソッド add(capture#1-of ? extends Dog) は引数に適用できません (Collie)

もちろん、これは予想通りです。

于 2012-10-15T11:18:31.413 に答える
1

この参照はたとえば a を保持する可能性があるため、単に aCollieに a を追加することはできません。List<? extends Dog>List<Spaniel>

于 2012-10-15T11:24:48.507 に答える
0

コードを IDEONE http://ideone.com/msMcQに貼り付けました。それは私のためにコンパイルされませんでした-これは私が期待したものです。コンパイルエラーはありませんでしたか?

于 2012-10-15T11:21:55.273 に答える
0

この質問に対する答えは、メソッドがワイルドカードのジェネリック typ を使用する場合、コレクションにアクセスまたは変更できますが、両方はできないことを示しています。(キャシーとバート)

これは公正な最初の概算ですが、正確ではありません。より正しいのは次のとおりです。

Collection<? extends Dog>add メソッドは の引数を取るため、null のみを a に追加できます? extends Dog。メソッドを呼び出すときは常に、宣言されたパラメータ タイプのサブタイプのパラメータを渡す必要があります。ただし、パラメーターの型? extends Dogの場合、コンパイラーは、式が である場合にのみ、引数が互換性のある型であることを確認できますnull。ただし、もちろん、clear()またはを呼び出してコレクションを変更できますremove(Object)

一方、 a から読み取る場合Collection<? super Dog>、そのイテレータの戻り値の型は? super Dogです。つまり、 の未知のスーパータイプのサブタイプであるオブジェクトを返しますDog。ただし、別の方法として、 Collection は のCollection<Object>インスタンスのみを含む である可能性がありますString。したがって

for (Dog d : collection) { ... } // does not compile

したがって、私たちが知っている唯一のことは、オブジェクトのインスタンスが返されることです。つまり、そのようなコレクションを反復する唯一の型正しい方法は

for (Object o : collection) { ... }

コレクションから読み取ることは可能ですが、取得するオブジェクトのタイプがわからないだけです。

その観察結果を次のように簡単に一般化できます。

class G<T> { ... }

G<? extends Something> g;

宣言された type を持つメソッド パラメータに null のみを渡すことができますがT、戻り値の型を持つメソッドを呼び出しT、結果を type の変数に割り当てることができますSomething

一方、

G<? super Something> g;

宣言された type を使用して、型の任意の式Somethingをメソッド パラメーターに渡すことができますT。また、戻り値の型を使用してメソッドを呼び出すこともできますがT、結果は型の変数にのみ割り当てることができますObject

要約すると、ワイルドカード型の使用に関する制限は、メソッドの機能ではなく、メソッド宣言の形式のみに依存します。

于 2012-10-15T11:49:15.603 に答える