2017-04-11 10 views
1
List<Integer> ints = new ArrayList<Integer>(); 
ints.add(1); ints.add(2); 
List<? extends Number> nums = ints; 
nums.add(3.14); // compile-time error 
assertints.toString().equals("[1, 2, 3.14]"); 

なぜ我々は、コンパイル時エラーを取得していますか?ジェネリックは

+0

参照:http://stackoverflow.com/questions/5495383/java-generics-wildcard-question-list-extends-a?rq=1 –

+0

http://stackoverflow.com/a/6439506/2928853 – jrook

答えて

1

これは、Javaジェネリックのタイプの消去のためです。 コンパイル時に型パラメータが定義されていないため、新しい要素をリストに追加することはできません。 リストList<? extends Number> numsは、addメソッドを呼び出すことができないことを意味します。

1

List<? extends Number>は、それがNumberであること以外に、どのタイプがリストにあるかわからないことを意味します。この場合

、それがList<Integer>です。 List<? extends Number>に割り当てても、基本的にはList<Integer>のままです。そして、そのようなリストに3.14を追加することはできません。

これが許された場合は、次のコードは、有効な次のようになります。

List<Integer> ints = new ArrayList<Integer>(); 
ints.add(1); ints.add(2); 
List<? extends Number> nums = ints; 
nums.add(3.14); 
Integer third = ints.get(2); 

しかしints.get(2)は整数ではないので、ここでは、例外をスローします。この種の問題をコンパイル時に捕らえたほうがよい。

+0

私は 'nums'は何とかIntegersのリストのまま残っているとは少し不正確だと思います。浮動小数点数を追加できないだけでなく、整数を 'nums'リストに追加することさえできません。 'nums.add(新しい整数(1))'はまだコンパイルされません。 – jrook

+0

@jrookと同意する...エラーが発生した時点で、コンパイラは 'nums'が' List <? Number> 'を継承します。 'num 'に割り当てられていたものを追跡しません。したがって、 'nums'が' Integer'のリストであることに基づいてコンパイル時エラーを得ることはできません。この種のエラーは実行時に捕捉される可能性がありますが、この特定のケースではタイプ消去のために捕捉できない可能性があります。 – ajb

0

ここで重要な部分は、具体的にIntegerをListクラスに渡すインスタンス化(new ArrayList<Integer>())です。左側のダイヤモンド表記は、互換性がある限りはそれほど重要ではありません。後であなたはIntegerの上位境界としてジェネリックを定義しています(主にNumberとそのサブタイプ)ので、Javaはそれでも問題はありません。オブジェクトは本質的にまだList<Integer>です。

これは、オブジェクトにStringを割り当てる場合と同じです。 ObjectStringのスーパータイプであるため、動作します。ここでList<? extends Number>は、List<Integer>というスーパータイプのようなものです。 (私は言葉「スーパータイプ」はここで間違っているので、私を修正すること自由に感じ知っている。)

ジェネリック医薬品とのインスタンス化は一種のクラス自体やオブジェクトのインスタンス化のようなものです。その他の言語Pythonはこの種の動作に「メタクラス」という用語を使用しています。

+0

"スーパークラス"が使われているのを見たので、 "スーパータイプ"が間違っていればそれほど間違っていません。 – ajb

関連する問題