これは、スタンフォードパーサーに付属するいくつかの例から抜粋した小さなコードスニペットです。私は約4年間Javaで開発してきましたが、このスタイルのコードが何を示すことになっているのかを非常に強く理解したことはありません。
List<? extends HasWord> wordList = toke.tokenize();
コードの詳細については心配していません。私が混乱しているのは、一般的な表現が正確に英語で伝えているはずのものです。
誰かがこれを私に説明できますか?
これは、スタンフォードパーサーに付属するいくつかの例から抜粋した小さなコードスニペットです。私は約4年間Javaで開発してきましたが、このスタイルのコードが何を示すことになっているのかを非常に強く理解したことはありません。
List<? extends HasWord> wordList = toke.tokenize();
コードの詳細については心配していません。私が混乱しているのは、一般的な表現が正確に英語で伝えているはずのものです。
誰かがこれを私に説明できますか?
回答:
? extends HasWord
「拡張するクラス/インターフェース」を意味しますHasWord
。つまり、HasWord
それ自体またはその子のいずれかです。基本的に、instanceof HasWord
plusで機能するものは何でもnull
。
より技術的な用語で言えば、139ページから始まる、Effective Java 3rd Editionの? extends HasWord
アイテム31で説明されている境界付きワイルドカードです。2ndEditionと同じ章がPDFとしてオンラインで入手できます。バインドされたワイルドカードの部分は、134ページから始まるアイテム28です。
更新:Oracleがしばらく前に削除したため、PDFリンクが更新されました。これは現在、ロンドンのクイーンメアリー大学の電子工学およびコンピュータサイエンススクールがホストするコピーを指しています。
更新2:ワイルドカードを使用する理由についてもう少し詳しく説明しましょう。
シグネチャが渡すことを期待しているメソッドを宣言する場合、渡すList<HasWord>
ことができるのはだけですList<HasWord>
。
ただし、その署名がList<? extends HasWord>
その場合は、List<ChildOfHasWord>
代わりに渡すことができます。
間に微妙な違いがあることに注意してくださいList<? extends HasWord>
とList<? super HasWord>
。Joshua Blochの言葉どおり、PECS =プロデューサー拡張、コンシューマースーパー。
つまり、メソッドがデータを取得するコレクションを渡す場合(つまり、コレクションがメソッドで使用する要素を生成している場合)は、を使用する必要がありますextends
。メソッドがデータを追加するコレクションを渡す場合(つまり、コレクションはメソッドが作成する要素を使用している場合)、を使用する必要がありますsuper
。
これは混乱するように聞こえるかもしれません。ただし、これはList
のsort
コマンドで確認できます(Collections.sortの2引数バージョンへのショートカットにすぎません)。をとる代わりにComparator<T>
、実際にはをとりますComparator<? super T>
。この場合、List
リスト自体を並べ替えるために、コンパレータはの要素を使用しています。
List<HasWord>
まさにあなたが説明するものです:true x
をx instanceof HasWord
返すオブジェクトを含むリスト、そしてnull
。これにはワイルドカードは必要ありません。ワイルドカードは、このタイプがのサブタイプである限り、実際には別のタイプのリストでもかまいませんHasWord
。(コメントが遅れて申し訳ありません。)
List<? extends HasWord>
HasWordを拡張する具象クラスを受け入れます。次のクラスがある場合...
public class A extends HasWord { .. }
public class B extends HasWord { .. }
public class C { .. }
public class D extends SomeOtherWord { .. }
... wordList
両方のクラスが同じ親またはnull
(親のinstanceofチェックに失敗するHasWorld
)を拡張するため、AsまたはBのいずれか、または両方の混合のリストのみを含めることができます
List<? extends Collection<String>> list = new ArrayList<List<String>>();
。
List<HasWord>
。これも同じように行います。ここでの要点は、この変数にはa List<A>
またはaを含めることができるList<B>
ということList<HasWord>
です。
おそらく、不自然な「実世界」の例が役立つでしょう。
私の職場では、さまざまな味のゴミ箱があります。すべてのゴミ箱にはゴミが含まれていますが、一部のゴミ箱は専門家であり、すべての種類のゴミを取りません。したがって、とがBin<CupRubbish>
ありBin<RecylcableRubbish>
ます。型システムはHalfEatenSandwichRubbish
、これらの型のどちらにも入れないようにする必要がありますが、一般的なゴミ箱に入れる可能性がありますBin<Rubbish>
。私が話をしたかった場合Bin
のRubbish
私は互換性のないゴミに置くことができないので、専門されることができる、それは可能でしょうBin<? extends Rubbish>
。
(注:? extends
読み取り専用を意味するものではありません。たとえば、私は適切な予防策を講じて、不明な専門分野のゴミ箱からゴミを取り出し、後で別の場所に戻すことができます。)
それがどれだけ役立つかわかりません。ポリモーフィズムが存在する場合のポインターツーポインターは完全には明らかではありません。
英語で:
それはだ
List
クラスを拡張し、いくつかのタイプのHasWord
を含め、HasWord
一般的に?
、ジェネリックのinは任意のクラスを意味します。そして、extends SomeClass
そのオブジェクトが拡張する必要があるSomeClass
(またはそのクラスである)ことを指定します。
疑問符は、ワイルドカードを定義するために使用されます。それらに関するOracleのドキュメントを確認してください。http://docs.oracle.com/javase/tutorial/java/generics/wildcards.html