Javaジェネリックの型パラメーターの疑問符はどういう意味ですか?


216

これは、スタンフォードパーサーに付属するいくつかの例から抜粋した小さなコードスニペットです。私は約4年間Javaで開発してきましたが、このスタイルのコードが何を示すことになっているのかを非常に強く理解したことはありません。

List<? extends HasWord> wordList = toke.tokenize();

コードの詳細については心配していません。私が混乱しているのは、一般的な表現が正確に英語で伝えているはずのものです。

誰かがこれを私に説明できますか?


回答:


226
? extends HasWord

「拡張するクラス/インターフェース」を意味しますHasWord。つまり、HasWordそれ自体またはその子のいずれかです。基本的に、instanceof HasWordplusで機能するものは何でも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

これは混乱するように聞こえるかもしれません。ただし、これはListsortコマンドで確認できます(Collections.sortの2引数バージョンへのショートカットにすぎません)。をとる代わりにComparator<T>、実際にはをとりますComparator<? super T>。この場合、Listリスト自体を並べ替えるために、コンパレータはの要素を使用しています。


17
「instanceofで機能するもの」-null値。null値は、どのinstanceofチェックでもfalseを返すことに注意してください。
Eyal Schneider

12
インターフェイスを忘れないでください。?クラスを表す必要はありません!
マークピーターズ

9
List<HasWord>まさにあなたが説明するものです:true xx instanceof HasWord返すオブジェクトを含むリスト、そしてnull。これにはワイルドカードは必要ありません。ワイルドカードは、このタイプがのサブタイプである限り、実際には別のタイプのリストでもかまいませんHasWord。(コメントが遅れて申し訳ありません。)
PaŭloEbermann '12 / 08/12

1
PDFリンクは機能していないようですが、これは私にとって役に立ちました:docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
user1338062

奇妙なことに、昨年@ user1338062が投稿したときにメッセージが届かず、PDFリンクが機能していないことを知りませんでした。今修正されました。本自体へのリンクも追加しました。
Powerlord 2013

65

疑問符は、「任意のタイプ」の記号です。 ?一人で

拡張する任意のタイプObject(を含むObject

上記の例は

拡張または実装する任意のタイプ HasWord(非抽象クラスのHasWord場合 を含むHasWord


2
どういうpublic Set<Class<?>> getClasses()意味ですか?はどう違いSet<Class>ますか?私は見ていjavax.ws.rs.core.Applicationます。
ボールト

14

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のいずれか、または両方の混合のリストのみを含めることができます


8
具象だけでなく、サブクラスも抽象化します。
bloparod 2010年

2
コンクリートや抽象サブクラスでなく、サブインターフェースだけでなく、: List<? extends Collection<String>> list = new ArrayList<List<String>>();
マークピーターズ

2
実際にはこれにはワイルドカードは必要ありませんList<HasWord>。これも同じように行います。ここでの要点は、この変数にはa List<A>またはaを含めることができるList<B>ということList<HasWord>です。
–PaŭloEbermann、2011

12

おそらく、不自然な「実世界」の例が役立つでしょう。

私の職場では、さまざまな味のゴミ箱があります。すべてのゴミ箱にはゴミが含まれていますが、一部のゴミ箱は専門家であり、すべての種類のゴミを取りません。したがって、とがBin<CupRubbish>ありBin<RecylcableRubbish>ます。型システムはHalfEatenSandwichRubbish、これらの型のどちらにも入れないようにする必要がありますが、一般的なゴミ箱に入れる可能性がありますBin<Rubbish>。私が話をしたかった場合BinRubbish私は互換性のないゴミに置くことができないので、専門されることができる、それは可能でしょうBin<? extends Rubbish>

(注:? extends読み取り専用を意味するものではありません。たとえば、私は適切な予防策を講じて、不明な専門分野のゴミ箱からゴミを取り出し、後で別の場所に戻すことができます。)

それがどれだけ役立つかわかりません。ポリモーフィズムが存在する場合のポインターツーポインターは完全には明らかではありません。


5

英語で:

それはだListクラスを拡張し、いくつかのタイプのHasWordを含め、HasWord

一般的に?、ジェネリックのinは任意のクラスを意味します。そして、extends SomeClassそのオブジェクトが拡張する必要があるSomeClass(またはそのクラスである)ことを指定します。


1
実際には、classの代わりに入力してください。これはインターフェースに対しても同様に機能します。
–PaŭloEbermann、2011

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.