12

次のコードでは、get()が呼び出され、その結果が 型の変数に代入されますList<List<?>>get()は a を返し、List<List<T>>型パラメータTが に設定されているインスタンスで呼び出される?ため、適合するはずです。

import java.util.List;

class Test {
    void foo(NestedListProducer<?> test) {
        List<List<?>> a = test.get();
    }

    interface NestedListProducer<T> {
        List<List<T>> get();
    }
}

しかし、IntelliJ IDEA と Oracle のjavacバージョン 1.7.0_45 の両方が、私のコードを無効として拒否します。これは「javac」のエラー メッセージです。

java: incompatible types
  required: java.util.List<java.util.List<?>>
  found:    java.util.List<java.util.List<capture#1 of ?>>

このコードが無効なのはなぜですか。

4

4 に答える 4

7

?、任意のタイプを意味するワイルドカードです。別のは他のタイプである可能性があり、それらは一致しないため、1 つ?は別の と同じにすることはできません。タイプが同じであることを示すには、ジェネリックを使用する必要があります。??

// Make this generic
<A> void foo(NestedListProducer<A> test) {
    List<List<A>> a = test.get();
}
于 2013-11-14T17:53:12.687 に答える
4

List<?>コンパイラが aと aをどのように扱うかについて混乱しているようですList<List<?>>。AList<?>不明Listなタイプの であるのに対し、は(不明な異なるタイプの) です。List<List<?>>ListList

の場合List<?>、ワイルドカード?は単一の不明な型を表すため、コンパイラによってその単一の不明な型のプレースホルダーにキャプチャされます。ではList<List<?>>、ワイルドカード?はさまざまな不明なタイプを表します。さまざまな未知の型に対して単一のプレースホルダーが存在できないため、コンパイラはそのような型をキャプチャしません。

元の例を考えてみましょう:

void foo(NestedListProducer<?> test) {
    List<List<?>> a = test.get();
}

この場合、コンパイラはコンパイル時に をキャプチャし?NestedListProducer匿名型パラメータを作成し、次のようなヘルパー メソッドを作成します。

<CAP#1 of ?> void foo_2(NestedListProducer<CAP#1 of ?> test) {
    List<List<?>> a = test.get();
}

(注: in をキャプチャしない?ためList<List<?>>、そのまま残ります)。

test.get()この場合の戻り値の型はになりますList<List<CAP#1 of ?>>。から変換可能な割り当てキャプチャではないList<List<?>>ため、それに割り当てることはできません。したがって、コンパイルに失敗します。

したがって、回避策は、すでに提案されているように、型パラメーターを自分で追加することです。

<T> void foo(NestedListProducer<T> test) {
    List<List<T>> a = test.get();
}

コメントからのクエリ:

コメントで尋ねたように、次のコードが機能するのはなぜですか?

void foo(List<List<?>> arg) { 
    List<List<?>> a = arg; 
}

上記の説明から、仮パラメータのワイルドカードはキャプチャされないこと?が推測できます。List<List<?>>したがって、割り当ては実際には aList<List<?>>から toList<List<?>>であり、これは有効です。ここにはありませんCAP#1 of ?

于 2013-11-14T19:04:38.150 に答える
0

このトリックを使用できます (ワイルドカード キャプチャ)

void foo(NestedListProducer<?> test) {
    foo2(test);
}

<T> void foo2(NestedListProducer<T> test) {
    List<List<T>> a = test.get();
}
于 2013-11-14T18:23:03.620 に答える