Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java bounded wildcard in return type

I've read in various places including here that having a bounded wildcard in a method return type is a bad idea. However, I can't find a way to avoid it with my class. Am I missing something?

The situation looks something like this:

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;
    }
}

In summary, a class that I want to be able to consume any publication that is in some variant to English. The class needs to allow access to the publication from outside but, ideally, the callers of getPublication wouldn't want the result as a bounded wildcard. They would be happy with Publication<English>.

Is there a way round this?

like image 268
thehouse Avatar asked Jan 23 '12 02:01

thehouse


2 Answers

Bounded wildcards are contagious, which is what the page you link to seems to lament. Well, there's no denying that... but I guess I don't see it as such a big problem.

There are many cases where I return a bounded wildcard exactly because it's contagious. The JDK, for better or worse (I say for worse, but that's a different soap box :) ) doesn't have interfaces for read-only collections. If I return a List<Foo> that I don't want people modifying (maybe it's even safely wrapped in Collections.unmodifiableList), there's no way to declare that in my return signature. As a poor-man's workaround, I'll often return List<? extends Foo>. It's still possible to try to modify that list by removing elements or inserting null, but at least the fact that you can't add(new Foo()) serves as a bit of a reminder that this list is probably read-only.

More generally, I think returning something with a bounded return type is perfectly reasonable if you really want the call site to have restricted access to the object.

Another example would be a thread-safe queue that you hand off to different threads, where one thread is a producer and the other is a consumer. If you give the producer a Queue<? super Foo>, it's clear that you intend them to put items into it (and not take items out). Likewise, if you give the consumer a Queue<? extends Foo>, it's clear you intend them to take items out (and not put items in).

like image 179
yshavit Avatar answered Nov 18 '22 11:11

yshavit


Can you use a bounded type parameter in the class declaration?

class EnglishReaderOfPublications<E extends English> { ...

Then you can use this type parameter everywhere you have the wildcard parameter.

like image 24
Jordão Avatar answered Nov 18 '22 11:11

Jordão