2012-10-06 2 views
6

先日他の人のコードを見直していましたが、心配していた行を見つけました。単純化するために、私はジェネリッククラスAと抽象クラスBを持っていると言っています。次のインスタンス化は許されていますか?もしそうなら、なぜですか?ジェネリックスのワイルドカードのインスタンス

Object obj = new A<? extends B>(); 

A<? extends B> obj = null; 

として宣言は確かに保持するだろうが、私は個人的には、上記のようなインスタンス生成を見たことがありません。私はジェネリックでワイルドカードを使用してメソッドパラメータを宣言してきたので、経験がないかもしれません。

+0

どのJavaのバージョンを使用しますか? –

+0

が重複しない場合は関連します。http://stackoverflow.com/questions/9147129/creating-new-generic-object-with-wildcard and http://stackoverflow.com/questions/12200136/cannot-instantiate-type-in​​-ジェネリック?lq = 1 –

答えて

3

実際にはnew A<? extends B>()はコンパイルされません。 Java 5以降、一貫して違法となっています。

しかし元の例はnew A<X<? extends B>>()のようなものでした。後者は、最近のJavaのバージョンでは合法です。

オブジェクトをインスタンス化するとき、typeパラメータの値は任意の非ワイルドカード型にすることができます。 ? extends Bはワイルドカードタイプなので、許可されません。しかし、X<? extends B>はワイルドカード型ではありませんが、にはというワイルドカード型があります。したがって、法的にnew A<X<? extends B>>()と呼ぶことができます。

このように考えるとルールは意味があります。最終的には、? extends Bのようなワイルドカード型は、と宣言されたフィールドまたは変数の型ではないという基本的なルールの副産物です。 A

class A<T> { 
    T value; 
} 

として定義されている場合、仮想的なnew A<? extends B>().valueはタイプ? extends Bの宣言フィールドだろう。それは違法なので、インスタンス化もそうです。しかしnew A<X<? extends B>>()にはそのような問題はありません。

+0

かなり良い答えですが、私は後半の推論が理にかなっているとは思いません。変数 'a'が' A 'とタイプされていれば、' a.value'は '*として宣言されていますか? Bを拡張する - 'value'は' T'と宣言され、 'A'は' T'を宣言します。 'a.value'は*を評価するのですか? B 'を延長する。同様の質問[ここ](http://stackoverflow.com/a/9147768/697449)への私の答えを見てください。 –

+0

@PaulBellora第2部で私はあまり明確ではなかった。私が言いたいのは、_expression_ 'a.value'の推定型と_variable_' a.value'の宣言型の間に違いがあるということでした。変数はr値とl値の両方であることに注意してください。そうすれば、ワイルドカード型 '? (または ''スーパーT ')には、本質的に障害のある変数になります。 r値(それぞれl値)として使用することはできません。さて、これは普通のリファレンス 'a'では許容されますが、' this'では決して許されません。 – Saintali

関連する問題