ワイルドカードのパラメーター化された型のオブジェクトを作成できない理由を理解するには、まず、ワイルドカードのパラメーター化された型の用途を理解する必要があります。
ワイルドカードを使用する理由
ご存じのように、Java ジェネリックは不変です。したがって、型引数が共変であっても、List<Number>
a は のスーパークラスではありません。List<Integer>
では、異なるオブジェクトを指している同じ参照を持つなど、ジェネリックスでもそのような動作が必要な場合はどうでしょうか? あなたが名前を付けるように、その多形的なもの。、、またはList
のリストを参照する単一の参照が必要な場合はどうすればよいでしょうか?Integer
Float
Double
救助へのワイルドカード:
ワイルドカードを使用すると、上記の動作を実現できます。したがって、 aは a 、などList<? extends Number>
を参照できます。したがって、次の宣言が有効です。List<Integer>
List<Double>
List<? extends Number> numbers = new ArrayList<Integer>();
numbers = new ArrayList<Double>();
numbers = new ArrayList<Float>();
numbers = new ArrayList<String>(); // This is still not valid (you know why)
では、ここで何を変更したのでしょうか。の参照型だけnumbers
です。より強力なコンパイル時チェックを実施するために、ジェネリックが Java に導入されたことに注意してください。したがって、パラメーター化された型の宣言が規則に準拠しているかどうかを判断するのは、主にコンパイラーの仕事です。ワイルドカードがない場合、コンパイラは への参照に対してエラーを表示List<Number>
しますList<Integer>
。
したがって、ワイルドカードは、ジェネリックに共分散のような動作を導入するための単なる方法です。ワイルドカードを使用すると、柔軟性が向上します。つまり、コンパイラが適用する制限が緩和されます。List<? extends Number>
参照は、リストがのリストまたは任意のサブタイプを参照できることをコンパイラに伝えます(Number
もちろんNumber
、下限のワイルドカードもありますが、それはここでは重要ではありません。それらの違いは、SOのみに関する他の多くの回答ですでに説明されています)。
メソッド パラメーターで見られるワイルドカードのパラメーター化された型の主な用途。単一のメソッド パラメーターに対してジェネリック型の異なるインスタンス化を渡したい場合:
// Compiler sees that this method can take List of any subtype of Number
public void print(List<? extends Number> numbers) {
// print numbers
}
ただし、実行時にオブジェクトを作成するには、具象型を指定する必要があります。ワイルドカード (制限付きまたは制限なし) は具象型ではありません。? extends Number
のサブタイプであるすべてを意味しNumber
ます。では、 を作成するときに、どのタイプのList
が作成されることを期待しますList<? extends Number>
か? このケースは、 をインスタンス化できない理由と似ていると考えることができますinterface
。それらは単なる具体的なものではないからです。
回避策があります。本当に?
これは違法ですが、 - Java Generics FAQで説明されているように、回避策があることを知って驚かれることでしょう。しかし、私は本当にあなたがそれを必要とするとは思わない.