2011-07-20 15 views
3

Generics Tutorialを経由して、オブジェクトを配列からコレクションにコピーしています。ジェネリックス:コレクションのパラメータとしてObjectを使用できないのはなぜですか?

コード

static void fromArrayToCollection(Object[] a, Collection<?> c) { 
    for (Object o : a) { 
     c.add(o); // Compile time error 
    } 
} 

私はコレクションにオブジェクトをパラメータとして渡すことができ、それは何の問題もなく動作するはずですが、チュートリアルでは、

が今では、あなたが避けるために学んできたであろうと言うことを考えていますコレクションパラメータの型としてCollectionを使用しようとする初心者の間違い。

なぜObjectをパラメータ型としてCollectionに渡すのが正しい方法ではないのですか?更新

static void fromArrayToCollection(Object[] a, Collection<Object> c) { 
    for (Object o : a) { 
     c.add(o); // Compile time error 
    } 
} 
+3

genericが存在する理由の1つは、コレクション内のオブジェクトを使用する必要がないためです。 –

答えて

4

「初心者の間違い」とは、あなたが言っていることが「すべてのコレクション/何のコレクション」であるときにCollection<Object>と言っています。抽象的には、メソッドをCollection<Object>と宣言するのは完全に合法ですが、それは何かを取り込むメソッドの設計目標を満たしていないだけです。

は、我々はこれを行うことができるようにしたい:あなたはそれCollection<Object>行われた場合に動作しないでしょう

public static void main(String[] args) { 
    String[] stringArray = {"A", "B", "C"}; 
    List<String> stringList = new ArrayList<String>(); 
    fromArrayToCollection(stringArray, stringList); 
    Integer[] intArray = {1, 2, 3}; 
    List<Integer> intList = new ArrayList<Integer>(); 
    fromArrayToCollection(intArray, intList); 
} 

public static <T> void fromArrayToCollection(T[] array, Collection<T> collection) { 
    for (T item: array) { 
     collection.add(item); 
    } 
} 

を。

パラメータタイプをCollection<Object>と宣言することはできません。ジェネリックタイプは共変ではないため、上記のような複数のタイプに対しては機能しません。言うには、List<String>を引数型がCollection<Object>のメソッドに渡すのは違法です。 Collection<String>Collection<Object>ではありません。それはCollection<Object>としてそれを宣言し、何の集まりを取ることは違法だ理由です

List<Integer> intList = new ArrayList<Integer>(); 
List<Object> objList = intList; //doom impending!!! 
objList.add("NOTANUMBER"); 
int i = intList.get(0).intValue(); //runtime exception! 

は、標準的な例を考えてみましょう。

+0

:)!ちょうど私の心のように..! –

+0

合意しましたが、この場合、 'fromarraytocollection'関数の戻り値の型がオブジェクトであることを知っています。なぜ' fromarraytocollection'メソッドdefinationに 'Collection c as Collection c'がありませんか? – Rachel

+0

コンパイラを使用した場合、ユーザーはObject以外のCollectionの中を渡すことはできません。メソッド内で "安全でない"ことをしないと知っていても、コンパイラはそのメソッドを使用する人にそのことを保証できないため、その動作を許可しないといけません。 – Affe

0

何をしたいが、このです:

static <T> void fromArrayToCollection(T[] a, Collection<T> c) { 
    for (T o : a) { 
     c.add(o); // No compiler error 
    } 
} 

あなたも、配列を入力することができます。メソッドの型付きパラメータを宣言することによって、その型を各入力に渡すことができます。

static void fromArrayToCollection(Object[] a, Collection<? super Object> c) { 
    for (Object o : a) { 
     c.add(o); // No compiler error 
    } 
} 

をしかし、これは少し陳腐に思える:

また、これを行うことができます。

+0

私はこれが必要ですが、私の質問はなぜ私のコレクションのパラメータとしてオブジェクト型を使用できないのですか? – Rachel

+0

私はあなたの説明を理解することができません、コレクションのパラメータとしてオブジェクトを渡すことが良いアプローチとは考えられないのですか? – Rachel

1

hereの説明の後に、Collection of Somethingが実際にオブジェクトのコレクションであることに頼るべきではないことがわかるので、Unknowのコレクションを使用すべきだと伝えますが、そのコレクションには何も追加できませんあなたはそれを破損する可能性があります。

static void fromArrayToCollection(Object[] a, Collection<?> c) { 
    for (Object o : a) { 
     c.add(o); // Imagine that this will compile 
    } 
} 

// somewhere else in the same class 
Collection<String> myStrings = new ArrayList<String>(); 
fromArrayToCollection(someListOfObjects, myStrings); 
myStrings.get(0).doSomethingOnlyStringsDo(); // surprise, surprise, i am not a string. 
2

あなたのコードは、次のと同等です::以下想像

static void <T> fromArrayToCollection(Object[] a, Collection<T> c) { 
    for (Object o : a) { 
     c.add(o); // Compile time error 
    } 
} 

例えばT.の種類に制限はありませんので、それは動作しません、あなたが設定することができますTへIntegerであり、Objectの任意のインスタンスをIntegerのコレクションに追加すると言っています。

これが役に立ちます。