Java在返回类型中绑定了通配符

时间:2012-01-23 02:01:35

标签: java generics bounded-wildcard

我在包括here在内的各个地方读过,在方法返回类型中使用有界通配符是一个坏主意。但是,我无法找到一种方法来避免与我的班级。我错过了什么吗?

情况看起来像这样:

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>感到满意。

有没有办法解决这个问题?

3 个答案:

答案 0 :(得分:13)

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

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

更一般地说,如果你真的希望调用网站能够限制访问该对象,我认为返回带有有界返回类型的内容是完全合理的。

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

答案 1 :(得分:5)

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

class EnglishReaderOfPublications<E extends English> { ...

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

答案 2 :(得分:0)

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

为什么“不会”他们想要它?他们会对Publication<? extends English>“感到高兴”吗?问题实际上是这些调用者需要对此Publication对象执行的操作。如果他们所做的一切都是从中得到的东西,那么Publication<? extends English>就足够了,而且它更好,因为它更通用。但是,如果他们需要将内容放入其中,那么您就无法使用Publication<? extends English>