1. ホーム
  2. java

[解決済み] Javaにおける<? super T>と<? extends T>の違い [重複]について

2022-03-19 21:55:01

質問

とはどのような違いがあるのでしょうか? List<? super T>List<? extends T> ?

以前は List<? extends T> しかし、これでは要素を追加することができません。 list.add(e) 一方 List<? super T> を行います。

どのように解決するのですか?

extends

のワイルドカード宣言は List<? extends Number> foo3 は、これらのどれもが合法的な代入であることを意味します。

List<? extends Number> foo3 = new ArrayList<Number>();  // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>();  // Double extends Number

  1. 読み方 - 上記のような割り当てが可能な場合、どのようなタイプのオブジェクトからの読み取りが保証されているか List foo3 :

    • を読むことができます。 Number に割り当てられる可能性のあるリストのどれかが、このリストに割り当てられるからです。 foo3 が含まれています。 Number またはそのサブクラス Number .
    • を読み取ることはできません。 Integer なぜなら foo3 を指している可能性があります。 List<Double> .
    • を読み取ることはできません。 Double なぜなら foo3 を指している可能性があります。 List<Integer> .
  2. 執筆 - 上記のような割り当てが可能な場合、どのようなタイプのオブジェクトを List foo3 にとって合法的なものである。 すべて 上記の可能な ArrayList を割り当てます。

    • を追加することはできません。 Integer なぜなら foo3 を指している可能性があります。 List<Double> .
    • を追加することはできません。 Double なぜなら foo3 を指している可能性があります。 List<Integer> .
    • を追加することはできません。 Number なぜなら foo3 を指している可能性があります。 List<Integer> .

にオブジェクトを追加することはできません。 List<? extends T> がどのようなものであるか保証できないからです。 List を指しているので、そのオブジェクトがその List . 唯一の "保証" は、そこから読み取ることだけが可能で、そのためには T またはそのサブクラスである T .

super

ここで、次のことを考えます。 List <? super T> .

のワイルドカード宣言は List<? super Integer> foo3 は、これらのどれもが合法的な代入であることを意味します。

List<? super Integer> foo3 = new ArrayList<Integer>();  // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>();   // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>();   // Object is a superclass of Integer

  1. 読み方 - 上記のような代入が可能である場合、 List foo3 :

    • を保証するものではありません。 Integer なぜなら foo3 を指している可能性があります。 List<Number> または List<Object> .
    • が保証されているわけではありません。 Number なぜなら foo3 を指している可能性があります。 List<Object> .
    • のみ のインスタンスを取得することが保証されています。 Object またはそのサブクラスである Object (ただし、どのサブクラスかわからない)。
  2. 執筆 - 上記のような割り当てが可能な場合、どのようなタイプのオブジェクトを List foo3 にとって合法的なものである。 すべて 上記の可能な ArrayList を割り当てます。

    • を追加することができます。 Integer なぜなら Integer は上記のどのリストでも許可されます。
    • のサブクラスのインスタンスを追加することができます。 Integer のサブクラスのインスタンスは Integer は、上記のどのリストでも許可されます。
    • を追加することはできません。 Double なぜなら foo3 を指している可能性があります。 ArrayList<Integer> .
    • を追加することはできません。 Number なぜなら foo3 を指している可能性があります。 ArrayList<Integer> .
    • を追加することはできません。 Object なぜなら foo3 を指している可能性があります。 ArrayList<Integer> .

PECS

リメンバー PECS : 生産者は拡張し、消費者は拡張する。 .

  • "プロデューサーエクステンド" - が必要な場合は List を生成するために T の値(あなたが読みたいのは T で宣言する必要があります。 ? extends T は、例えば List<? extends Integer> . しかし、このリストに追加することはできません。

  • "コンシューマースーパー" - が必要な場合は List を消費するために T の値を書きたい)。 T をリストに入れる) には、それを ? super T は、例えば List<? super Integer> . しかし、このリストからどのような種類のオブジェクトを読み取ることができるかは保証されていない。

  • リストからの読み込みとリストへの書き込みの両方が必要な場合、ワイルドカードを使わずに正確に宣言する必要があります。 List<Integer> .

使用例

備考 この例は、Java Generics FAQに掲載されています。 . ソースリスト src (生成リスト)は extends であり、宛先リスト dest (消費リスト) は super :

public class Collections { 
  public static <T> void copy(List<? super T> dest, List<? extends T> src) {
      for (int i = 0; i < src.size(); i++) 
        dest.set(i, src.get(i)); 
  } 
}

以下もご参照ください。 List<? extends Number> データ構造に追加するにはどうすればよいですか?