Javaプログラミングのアイデアの読書では、一般的なワイルドカードの上下の修飾は、この作品を理解するのは少し難しいです。実際には、私は通常、このワイルドカードを使用しないでください、ちょうど検索するためにインターネットに行くために少し混乱して見て、答えと自分の発言を持って、それらのほとんどは私が望むものではありません。ジェネリックの利点は、プログラミング言語の良い機能として、多くの言語がジェネリックをサポートしている、あまり言うことはありません。Javaコーディングでは、ジェネリックスは、より多くの拡張を達成するためにワイルドカードと組み合わせることができます。
Javaでは、"?" をジェネリック・パラメーターのワイルドカードとして使用します。 ジェネリック・パラメータのワイルドカードとして"? "を使用します。プレースホルダーにすることができます。
一番の疑問点
Javaはワイルドカードを使用して、extendsやsuperによって将来コンテナを指すために使用できるパラメータの種類を制限します:
- 格下げ: ? extends E
- 上位資格:? super E
私が最初に一番戸惑ったのは、対応するワイルドカード型がそのデータを保持できることをコンパイラがどうやって知ったのかということでした。
この2つの最も基本的な理解:
- < ? extends E >
- add: 要素の 追加を 許可しません!
- get: エレメントを得ることはできますが、エレメントを受け入れるには Eを 使わなければなりません!
- < ? super E >
- add: EおよびE要素のサブクラスを 追加できます!
- get:要素を取得できますが、クラス情報は失われるため、Object参照でしか返せません!独自の型が必要な場合は、型変換を行う必要があります!
分析する前に知るべきこと
そのため、getやaddが許可されている場合は、型安全性を確保するために型判定を行わなければなりません!これらの判断は、パラメータ範囲のソースに基づいて行われます!ここで問題なのは、私が知っているのは範囲だけで、ArrayListの背後に何があるのかは知らないということです。そこで私ができる唯一の判断は、Eの親クラスかEのサブクラスのオブジェクトしか追加できないように指定することです!でも最終的にはArrayListに追加するしかないでしょう。しかし、最終的にはArrayListに追加されることになるので、どのような型が指定されても型安全なArrayListでなければなりません!
インスタンスコード
ArrayList<C> al = new ArrayList<C>();
al.add(new C());
List<? extends A> list = al;
// list要素が追加されることは許されない。
// list.add(new A());
// list.add(new B());
// list.add(new C());
// list要素を得ることはできるが、受け入れる要素はAでなければならない!
A a1 = list.get(0);
// C c1 = list.get(0); Cでは受け付けられない
List<? super C> list1 = new ArrayList<B>();
// listCの親クラスから要素を追加することは許されない。
// list1.add(new A());
// list1.add(new B());
list1.add(new C()); //CとCのサブクラスを追加できる
// listlistを使うとクラス情報が失われてしまうので、強制的に型変換して要素を取得する必要がある。
// C c2 = list1.get(0);
C c2 = (C)list1.get(0);
分析中
< ? extends E >
- < ? extends A > リストはAのサブクラスであることを意味します!
- そして、AサブクラスとA親の2つのスコープを設定します。
- addの場合:
- Aサブクラスの場合:addの要素がAのサブクラスであることを許可すると、ジェネリックパラメータが? はAを拡張するので、ArrayListは型もAのサブクラスであることを指定することができ、addのオブジェクトがサブクラスのオブジェクトのArrayList指定型でなければならないという保証はありません、例えば:ArrayListはC、リストを指定しましたが、A()オブジェクトを追加 - これは違法です!したがって、そのスコープのサブクラスは動作しません!
- 親クラスの場合:ArrayList指定型は(?A]スコープでなければなりません!
- getの場合。
- listの場合、どのような型のArrayListをデポジットしているのか分かりませんが、Aへの参照を使えばArrayListの要素を受け入れることは間違いないでしょう!なぜなら、Aは間違いなく中の要素の親だからです!しかし、ArrayListの型があなたが指定した型の親である場合、それは受け入れられませんので、他の型を使用した場合は動作しません。
- addの場合:
- そして、AサブクラスとA親の2つのスコープを設定します。
< ? super E >
- < ? super C > リストは、Cとその親クラスの内部に格納されていることを意味します。
- 同じように、Cのサブクラス、Cの親クラスに分けられます。
- を追加します:
- ArrayListはCとその親クラスの範囲を指定するので、ArrayListはその仮想範囲のすべてのオブジェクトを正確に受け入れることができます。 つまり、Cのサブクラスの範囲は実現可能であり、判定基準がまったく決まらず、コンパイラが何をすべきかわからないextendsとは異なり、型判定の標準的な基準が存在します。
- Cの親クラス:明らかに上記のAサブクラスの状況と同じです!listはArrayListで指定された型を知ることができないので、判定基準を決めることができません。
- を追加します:
- を取得します。
- リストのみCのサブサブクラスオブジェクトを追加することができますので、あなたも考えているかもしれません:その後、私は直接Cを使用するArrayListのデータを受け入れることができないのですか?いいえ、ArrayListはlistに代入された時点で既に値を持っている可能性があり、この値がArrayListで指定された型であり、Cの親である場合、Cはそれを受け入れることができません! そして、listはArrayListがどの型を指定するのかわからず、範囲しか知らないので、どの親クラスなのか判断できないので、単純に確実に受け入れることができるObjectを使用することで、Objectしか受け入れることができないという事実を返し、そうでなければ強力な転送を行う必要があります。
- 同じように、Cのサブクラス、Cの親クラスに分けられます。
実は、最初はArrayListの範囲の後に追加するように制限できないものかと考えていました。
---- 理由は簡単で、リストを使っている編集者はArrayListが何であるかを知らないからです!
そして、なぜスーパーは大丈夫なんだろう、なぜ追加できるんだろう、と。
---- なぜなら、SUPERが配置されていても、それはわからないし、SUPERは通常の論理的な判断でADDすることができるからです!