2012-01-23 8 views
16

hereなどのさまざまな場所で、メソッドの戻り値の型にバインドされたワイルドカードを持つことは悪い考えです。しかし、私はクラスでそれを避ける方法を見つけることができません。何か不足していますか? は英語にはいくつかの変種であるあらゆる出版物を消費するように要約する戻り値の型でJava境界付きワイルドカード

class EnglishReaderOfPublications { 

    private final Publication<? extends English> publication; 

    EnglishReaderOfPublications(Publication<? extends English> publication) { 
     this.publication = publication; 
    } 

    void readPublication() { 
     publication.omNomNom(); 
    } 

    Publication<? extends English> getPublication() { 
     return publication; 
    } 
} 

、私はできるようにしたいクラス:

状況は、次のようになります。クラスは外部からのパブリケーションへのアクセスを許可する必要がありますが、理想的には、getPublicationの呼び出し元は結果を境界のあるワイルドカードとしては望んでいません。彼らはPublication<English>に満足しています。

これには方法がありますか?

+0

Joshua Blochの「Effective Java」の項目28では、「戻り値の型としてワイルドカード型を使用しないでください。 –

答えて

12

バインドされたワイルドカードは伝染性があり、リンク先のページは嘆かわしいようです。まあ、それを否定することはありません...しかし、私はそれが大きな問題としてそれを見ていないと思います。

境界のあるワイルドカードを正確にに返すケースが多く、は伝染性があるためです。 JDKは、良くても悪くても(私は悪いと言いますが、それは別の石鹸ボックスです:))は、読み取り専用のコレクション用のインターフェイスを持っていません。私がList<Foo>を返すと、私は人々を改造したくないかもしれません(おそらくそれはCollections.unmodifiableListで安全にラップされています)、それを私のリターンシグネチャーで宣言する方法はありません。貧しい人の回避策として、私はしばしばList<? extends Foo>を返すでしょう。要素を削除したり、nullを挿入することでそのリストを修正しようとすることはまだ可能ですが、少なくともadd(new Foo())がこのリストは読み取り専用である可能性があるということはできません。

もっと一般的には、コール・サイトにオブジェクトへのアクセスを制限したい場合は、有界の戻り値型で何かを返すことは完全に合理的です。

もう1つの例は、別のスレッドにハンドオフするスレッドセーフなキューで、1つのスレッドはプロデューサで、もう1つはコンシューマです。プロデューサーにQueue<? super Foo>を渡すと、アイテムを置くことを意図していることは明らかです(アイテムを取り出さない)。同様に、あなたが消費者にQueue<? extends Foo>を与えるならば、あなたは彼らがアイテムを取りに出す(そしてアイテムを入れない)ことを意図していることは明らかです。

4

クラス宣言で境界型パラメータを使用できますか?

class EnglishReaderOfPublications<E extends English> { ... 

このタイプのパラメータは、ワイルドカードパラメータを使用するすべての場所で使用できます。

+1

私はそれが私の場合に役立つかどうかはわかりません。私はこれらの英語読者の異種のコレクションを持っています。私が気にするのは、それらが出版物であるということです。私の質問は、なぜ「出版物」が「出版物」と同じではないのかということです。英語> 'を拡張します。私はこれがコレクションの理由(なぜあなたはワイルドカードを満たしているが実際のタイプに違反しているものを追加するかもしれない)を得るが、出版物は実行時に言語を変更する方法を提供しないので、違う。 – thehouse

0

"理想的には、getPublicationの呼び出し側は、結果を境界のあるワイルドカードとしては望んでいません。Publication<English>で満足できます。"

なぜ彼らはそれを望んでいませんか?彼らはPublication<? extends English>と "幸せになる"でしょうか?問題は、これらの呼び出し側がこのPublicationオブジェクトで行う必要があることです。彼らが行うことがすべてそれから物事を得るならば、Publication<? extends English>で十分であり、より一般的であるのでより良いです。しかし、物事を入れる必要がある場合は、Publication<? extends English>を使用することはできません。

+0

基本的に汚染のため。呼び出しコードは、 'getPublication'を呼び出して各パブリケーションを取得し、' Set'に配置します。現時点では 'Set > 'を拡張しています。たぶん私は気難しいです。 – thehouse

+0

読みにくいですが、より一般的です。私は構文が残念ながら冗長であることに同意する。これらのクラス/メソッドがあなた自身のコードの中にあるならば、あなたが好きなら、読みやすい方法に進むことができます。他のユーザーが読むことを期待しているAPIを書いているのであれば、ワイルドカードを正しく取得することは非常に重要です。誰かが出版物を持っていれば残念です。あなたがタイピングしていると "怠け者"(または "かなり")のためにあなたのAPIでそれを使用することはできませんでした。 – yshavit

関連する問題