7

次のコード Java では、 list を作成しましたnums。宣言中に別のリストを割り当てることができます。ただし、 以外の新しいアイテムは追加できませんnull。それで、それnumsは読み取り専用であることを意味しますか?なんで?そのリストに新しいアイテムを追加することは可能ですか?

List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);

List<? extends Number> nums = ints;
nums.add(3.14); //Generates error
nums.addAll(ints);  //Generates error

nums.add(null);     //works
System.out.println(nums.get(0));    //works

私はこのリンクを通過しました。正確な理由はわかりません。

4

4 に答える 4

6

そのリストに新しいアイテムを追加することは可能ですか?

いいえ...そのコードは、「実際に」リストが何であるかを知らないためです。想像してみてください

List<String> strings = new ArrayList<>();
List<? extends Object> objects = strings; // This is fine
objects.add(new Object()); // Fortunately this *isn't* valid...
System.out.println(strings.get(0).length()); // Or what would this do?

基本的に、 のようなワイルドカードを使用すると、API を介して? extends Tのみ値を取得できます...そして のようなワイルドカードを使用する場合、API を介してのみ値? super T入れることができます - それが安全だからです。

于 2015-09-16T16:57:17.427 に答える
2

いいえ、読み取り専用ではありません...通常はそれが意図されていますが。

オブジェクトを指定List<? extends Number>すると、コンパイラはその型をX が Number の未知のサブタイプである型に変換します。List<X>したがって、オブジェクトにはadd(X)メソッドがあります。引数を指定してメソッドを呼び出すことができXます...たとえば、null.

また、 return であるため、 ...からの値で呼び出すこともできget()ます。直接呼び出すことは理にかなっていますが、機能しません。少しヘルパーが必要です。Xadd()get()list.add(list.get(i))

古典的な例はCollections.reverse(List<? extends Object> list). このメソッドはlist、ワイルドカードに関係なく を変更します。

clear()もちろん、任意のリストで のような変更メソッドを呼び出すこともできます。


そうは言っても、ワイルドカードは確かに主に use-site difference用であり、ほとんどの場合、型パラメーターがinとoutのどちらを対象としているかという API 設計者からの意図を伝えます。たとえば、 を宣言することにより、API は、リストに T を に注入する、または リストから T を取得List<? super/extends Foo>することを意図していることを表します。

ワイルドカードが読み取り/書き込み専用になるというのは誤解です。しかし、この誤解はほとんどのユースケースで機能します。そして、この誤解を持っている人が増えれば増えるほど、それは慣習になってしまいます...

ワイルドカードに関する私の記事を参照してください - http://bayou.io/draft/Capturing_Wildcards.html

于 2015-09-16T17:07:50.750 に答える
-1

ジェネリックはコンパイル時のみです。

したがって、コンパイラは、使用する実際の型を決定します。

List<? extends Number>

これは、オブジェクトの実際のタイプがわからないことを意味します。

したがって、コンパイラは、リストが持つ実際のタイプが何であるかを確認しません。

于 2015-09-16T16:57:49.103 に答える