このジェネリックコードのワイルドカードコンパイル時エラーについて説明してください。
//no compile time error.
List<? extends Number> x = new ArrayList<>();
//compile time error.
List<? extends Number> x = new ArrayList<? extends Number>();
このジェネリックコードのワイルドカードコンパイル時エラーについて説明してください。
//no compile time error.
List<? extends Number> x = new ArrayList<>();
//compile time error.
List<? extends Number> x = new ArrayList<? extends Number>();
ワイルドカードを使用してジェネリック型をインスタンス化することは無効な構文です。タイプとは、であるか拡張するタイプList<? extends Number>
のを意味します。このタイプのインスタンスを作成することは意味がありません。インスタンス化を使用すると、特定の何かを作成するためです。List
Number
new ArrayList<? extends Number>();//compiler:"Wait, what am I creating exactly?"
ワイルドカードを使用したジェネリック型は、変数とメソッドパラメーターに対してのみ意味があります。これにより、変数とメソッドパラメーターに割り当てる/渡すことができるものの自由度が高まります。
//compiler:"Okay, so passing in a List<Integer> or a List<Double> are both fine"
public void eatSomeNumbers(List<? extends Number> numbers) {
for (Number number : numbers) {
System.out.println("om nom " + number + " nom");
}
}
ワイルドカードの使用に伴う制限に注意してください。
List<? extends Number> numList = ...
numList.add(new Integer(3));//compiler:"Nope, cause that might be a List<Double>"
最初の例として、ひし形はJava 7の新機能であり、コンパイラーは、割り当てられた変数のタイプに基づいて、新しいジェネリックインスタンスのタイプを推測できます。この場合:
List<? extends Number> x = new ArrayList<>();
コンパイラはnew ArrayList<Number>()
ここで推論している可能性が高いですが、与えられた変数への有効な割り当てである限り、推論されたものはほとんど問題になりません。これが、ダイヤモンド演算子が導入された理由です。新しいオブジェクトのジェネリック型を指定することは、いくつかのジェネリック型が有効な代入/引数になる限り、冗長でした。
この推論は、Javaのジェネリックが型消去のために純粋にコンパイル時の言語機能であり、実行時に意味がないことを覚えている場合にのみ意味があります。ワイルドカードは、この制限のためにのみ存在します。対照的に、C#では、ジェネリック型の情報は実行時に残ります-ジェネリックワイルドカードはその言語には存在しません。
使用する
List<? extends Number> x = new ArrayList<Number>();
代わりは。