私はいつ使うべきか、いつ使わないべきかを理解していました.1冊の本で見つけた素晴らしい原則が1つあります。
Get and Put の原則:構造体から値を取得するだけの場合は extends ワイルドカードを使用し、値を構造体に入れるだけの場合は super ワイルドカードを使用し、get と put の両方を行う場合はワイルドカードを使用しないでください。
数値のコレクションを取得し、それぞれを double に変換して合計するメソッドを次に示します。
public static double sum(Collection<? extends Number> nums) {
double s = 0.0;
for (Number num : nums) s += num.doubleValue();
return s;
}
これは extends を使用するため、次の呼び出しはすべて有効です。
List<Integer>ints = Arrays.asList(1,2,3);
assert sum(ints) == 6.0;
List<Double>doubles = Arrays.asList(2.78,3.14);
assert sum(doubles) == 5.92;
List<Number>nums = Arrays.<Number>asList(1,2,2.78,3.14);
assert sum(nums) == 8.92;
extends が使用されていない場合、最初の 2 つの呼び出しは有効ではありません。
EXCEPTION : extends ワイルドカードで宣言された型に何も入れることはできません — すべての参照型に属する値 null を除きます。
add メソッドを使用するときは常に値を構造体に入れるので、スーパー ワイルドカードを使用します。以下は、数値のコレクションと整数 n を受け取り、ゼロから始まる最初の n 個の整数をコレクションに入れるメソッドです。
public static void count(Collection<? super Integer> ints, int n) {
for (int i = 0; i < n; i++) ints.add(i);
}
これは super を使用するため、次の呼び出しはすべて有効です。
List<Integer>ints = new ArrayList<Integer>();
count(ints, 5);
assert ints.toString().equals("[0, 1, 2, 3, 4]");
List<Number>nums = new ArrayList<Number>();
count(nums, 5); nums.add(5.0);
assert nums.toString().equals("[0, 1, 2, 3, 4, 5.0]");
List<Object>objs = new ArrayList<Object>();
count(objs, 5); objs.add("five");
assert objs.toString().equals("[0, 1, 2, 3, 4, five]");
super が使用されていない場合、最後の 2 つの呼び出しは有効ではありません。
例外 :すべての参照型のスーパー型である Object 型の値を除いて、スーパー ワイルドカードで宣言された型からは何も取得できません。
この原則は、次の質問でも説明されていますGet and Put ルール