18

我已经在包括这里在内的各个地方读到,在方法返回类型中使用有界通配符是一个坏主意。但是,我找不到在课堂上避免它的方法。我错过了什么吗?

情况看起来像这样:

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>

有办法解决这个问题吗?

4

3 回答 3

14

有界通配符具有传染性,这就是您链接到的页面似乎在感叹的内容。嗯,不可否认……但我想我不认为这是一个大问题。

在很多情况下,我返回有界通配符正是因为它具有传染性。JDK,无论好坏(我说更糟,但那是一个不同的肥皂盒 :))没有只读集合的​​接口。如果我返回一个List<Foo>我不希望人们修改的(也许它甚至被安全地包装在 中Collections.unmodifiableList),那么就无法在我的返回签名中声明它。作为穷人的解决方法,我会经常回来List<? extends Foo>。仍然可以尝试通过删除元素或插入来修改该列表null,但至少您不能add(new Foo())提醒您该列表可能是只读的。

更一般地说,如果您真的希望调用站点对对象的访问受到限制,我认为返回具有有限返回类型的东西是完全合理的。

另一个例子是一个线程安全队列,你将它交给不同的线程,其中一个线程是生产者,另一个是消费者。如果您给生产者 a Queue<? super Foo>,很明显您打算让他们将物品放入其中(而不是取出物品)。同样,如果您给消费者 a Queue<? extends Foo>,很明显您打算让他们取出物品(而不是放入物品)。

于 2012-01-23T04:42:11.870 回答
5

你可以在类声明中使用有界类型参数吗?

class EnglishReaderOfPublications<E extends English> { ...

然后,您可以在具有通配符参数的任何地方使用此类型参数。

于 2012-01-23T02:05:41.630 回答
0

“理想情况下,getPublication 的调用者不希望将结果作为有界通配符。他们会对 . 感到满意Publication<English>。”

为什么他们“不想要”?他们会“高兴”Publication<? extends English>吗?问题实际上是这些调用者需要对这个 Publication 对象做什么。如果他们所做的只是从中得到一些东西,那就Publication<? extends English>足够了,而且更好,因为它更通用。但是,如果他们需要把东西放进去,那么你就不能使用Publication<? extends English>.

于 2012-01-23T08:25:35.637 回答