3

次のコードは、Eclipse ではコンパイルされません。「Abc 型のメソッド putHelper(List,int,E) は、引数には適用できません (List <.capture#8-of extends E>",int,E)」

private <E> void putHelper(List<E> list, int i, E value) {
    list.set(i, value);
}

public <E> void put(List<? extends E> list, int toPos, E value) {
    // list.set(toPos,value);
    putHelper(list, toPos, value);
}

なぜそうなのかわかりませんか?以下のコードは正常に動作するためです。

  public <E> void put(List<? extends E> list,int fromPos, int toPos) {
  putHelper(list,fromPos,toPos);
  }

  private <E> void putHelper(List<E> list,int i, int j) {
  list.set(j,list.get(i));
  }

そして、ここでヘルパー メソッドがワイルドカード型をキャプチャできることは理解していますが、以前のコードではなぜできないのでしょうか?

編集: 3 番目のケースでは、put メソッドの型パラメーターを List<.? に変更すると、super E> リストを取る別のメソッドから put() メソッドを呼び出そうとすると、Eclipse はそれをコンパイルしません。「Abc 型の put(List<.? super E>,int,E) メソッドは引数に適用できません (List <.capture#6-of extends E>",int,E)」

public static <E> void insertAndProcess(List<? extends E> list) {

// Iterate through the list for some range of values i to j

    E value = list.get(i);

//Process the element and put it back at some index

    put(list, i+1, value);

//Repeat the same for few more elements
}

private static <E> void putHelper(List<E> list, int i, E value) {
    list.set(i, value);
}

public static <E> void put(List<? super E> list, int toPos, E value) {
    putHelper(list, toPos, value);
}

ここで、insertAndProcess() が put() メソッドを呼び出してその実装で使用するにはどうすればよいでしょうか。ユーザーはこれらのメソッドを ArrayList<.Integer> などで呼び出すことができますか?

4

3 に答える 3

2

これは、Producer Extends、Consumer Superの頭字語であるPECSとしても知られるGet and Put Principleによるものです。

これは SO の質問で説明されています: PECS (Producer Extends Consumer Super) とは何ですか?

しかし、基本的に:

public <E> void put(List<? extends E> list, int toPos, E value) {
   // list.set(toPos,value);
   putHelper(list, toPos, value);
}

<? extends E>Listはコンシューマーとして使用されている (要素を取得している) ため、ここでは使用できません。super代わりにを使用する必要がありextendsます。

public <E> void put(List<? super E> list, int toPos, E value) {
   // list.set(toPos,value);
   putHelper(list, toPos, value);
}

編集

2番目のケースでは、 への呼び出しを介して要素を生成しているため、プロデューサーListとして機能しているため、 を使用できます。get()extends

ただし、3番目の例では、同じリストに取得して入れているため、ワイルドカードをまったく使用できないと思います。

これはコンパイルされます:

public static <E> void insertAndProcess(List<E> list) {

    // Iterate through the list for some range of values i to j
    E value = list.get(i);

    // Process the element and put it back at some index
    putHelper(list, i+1, value);

    // Repeat the same for few more elements
}

同じリストから取得して設定するため、とにかくワイルドカードを使用する必要がないため、タイプEが何であれ同じでなければならないことに注意してください。

于 2014-06-24T06:14:13.853 に答える
0

List<E>List<? extends E>asは E のサブクラスを受け入れることができるE クラス オブジェクトのみを受け入れます。

List<E>メソッドがパスのみを受け入れることができると言うと、List<? extends E>リストに実際に含まれるオブジェクトのタイプがわからないため、コンパイラは混乱します。

Java では、これは違法であることに注意してください。

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

例えばList<Number> list = new ArrayList<Integer>();

2 番目の例では、リストは E のサブクラスを想定しており、渡すものは E オブジェクトのリストであるため、許可されています。例えばList<? extends Number> list = new ArrayList<Integer>();

于 2014-06-24T06:09:49.617 に答える