2

私はSCJP/OCPJPの勉強をしていますが、奇妙な継ぎ目があるサンプルの質問に出くわしました。

サンプルコードは、2つのジェネリックコレクションをインスタンス化しました。

List<?> list = new ArrayList<?>();
List<? extends Object> list2 = new ArrayList<? extends Object>();

質問に対する「正しい」答えは、このコードはコンパイルされますが、いずれかのコレクションに追加するとランタイムエラーが発生するというものでした。

このようなコードをコンパイルしようとすると、エラーが発生します。Javaチュートリアルでは、このタイプのコードすら示されていません。代わりに、通常、アップキャストの一部としてワイルドカードを使用します。

Collection<?> c = new ArrayList<String>();

上記の2つの一般的なコレクションは、正当なコードでさえありますか?私のロジックによる2番目は、インターフェイスのみを許可しません。最初のものは完全に役に立たないように見えます。制御を試みないジェネリックを使用するのはなぜですか?

4

4 に答える 4

4

優れたJavaジェネリックチュートリアルPDFをチェックしてください。より具体的には、ワイルドカードに関するセクションには、あなたの質問に対する答えが含まれています。

Collection<?> c = new ArrayList<String>();
c.add( new Object() );

の要素タイプが何を表すのかわからないcため、オブジェクトを追加することはできません。このメソッドは、コレクションの要素タイプであるタイプのadd()引数を取ります。E実際の型パラメーターが?である場合、それはいくつかの未知の型を表します。追加するために渡すパラメータはすべて、この不明なタイプのサブタイプである必要があります。タイプがわからないため、何も渡すことができません。唯一の例外はnull、すべてのタイプのメンバーであるです。

于 2011-12-30T19:38:19.973 に答える
2

実行時にTypeを宣言する場合は、次のようにすることができます。

public class Clazz1<T> {

private final List<T> list = new ArrayList<T>();

private List<T> getList() {
    return list;
}

/**
 * @param args
 */
public static void main(String[] args) {
    Clazz1<Integer> clazzInt = new Clazz1<Integer>();
    clazzInt.getList().add(2);
    System.out.println(clazzInt.getList());

    Clazz1<String> clazzString = new Clazz1<String>();
    clazzString.getList().add("test");
    System.out.println(clazzString.getList());
}

}
于 2011-12-30T19:45:36.270 に答える
1

私はこの答えの前にこれにいくらか答えました。 ?インスタンス化には使用できません。なぜコードがコンパイルされるのかわかりません。私が使用したJavaコンパイラはどれもそれを許可しません。あなたは以下によって上に示されていることをすることができます:

List<?> list = new ArrayList();

それはコンパイルして実行しますが、あなたはできませんでした:

list.add("hello world"); //This wouldn't compile
于 2011-12-30T19:31:09.477 に答える
0

newオブジェクトの具体的なインスタンスを生成します。具象インスタンスは、ジェネリックを含めて1つのタイプのみを持つことができます。これを知っていると、ワイルドカードはでは機能しませんnew

于 2011-12-30T21:20:44.140 に答える