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?
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).
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.
"ideally, the callers of getPublication wouldn't want the result as a bounded wildcard. They would be happy with Publication<English>
."
Why "wouldn't" they want it? Would they "be happy" with Publication<? extends English>
? The question is really what these callers need to do with this Publication object. If all they do is get things out of it, then Publication<? extends English>
is sufficient, and it is better because it is more general. However, if they need to put things into it, then you can't use Publication<? extends English>
.