Java: upcasting Collection<T> to Collection<U super T>
I have a Collection<T>
. I have a class TManager imp开发者_如何学Clementing an interface UManager which has a method getCollection()
that needs to return a Collection<U>
where U is an interface, and T is a class that implements U.
Aside from just casting it, e.g. return (Collection<U>)Tcoll;
, is there a more correct way to handle this?
I control all 4 classes/interfaces here. Am I wrong in declaring UManager.getCollection
as
public Collection<U> getCollection();
Should it be
public Collection<? extends U> getCollection()
?
It depends on what you need to do with the Collection. If you don't need to put anything into the returned collection, then use the extends parameter
public interface UInterface {
Collection<? extends UInterface> getCollection();
}
And be done with it. If in the future you do need to add to the collection, wrapping it in a new Collection and adding all does the job, ignore the performance for nothing hit of it (extra run time performance hit for a compile time issue).
If, however, the purpose is to return a mutable collection, then you can add a type parameter to your interface:
public interface UInterface<T extends UInterface> {
Collection<T> getCollection();
}
Then your implementation would be:
public class TClass implements UInterface<TClass> {
pubic Collection<TClass> getCollection();
}
The problem with this approach is that you absolutely must have a type parameter at runtime to use the interface to get a mutable collection out of it, or be referencing the concrete class.
It should be:
public Collection<U> getCollection();
Try to avoid bounded wildcards in return types.
Subclasses would just declare the returned reference type as Collection<U>
rather than Collection<T>
. That would eliminate your casts.
However, if you do see the need to have a bounded wildcard in the return type, then I guess you will have to return Collection<? extends U>
and won't need the cast.
i believe you want:
public Collection<? extends U> getCollection();
You can find some official docs about this here.
@Jason, you're right. The doc doesn't call out return types explictly, but it does work. Here's an example method that demonstrates the syntax:
public Collection<? extends Throwable> getErrors() {
return new ArrayList<Exception>();
}
Your topicstart was a bit confusing because one-character identifiers are usually used by generic types but you explicitly mentioned about an interface and a class. So are you looking for something like this?
interface UManager<T extends UInterface> {
Collection<T> getCollection();
}
class TManager implements UManager<TClass> {
public Collection<TClass> getCollection() {
return Arrays.asList(new TClass(), new TClass());
}
}
interface UInterface {
}
class TClass implements UInterface {
}
精彩评论