Why doesn't this work?
public class FooImpl implements Foo { /* ... */ }
public class Main {
public static <T> Collection<T> getList(Class<? extends T> itemClass) { /* ... */ }
public static void main(String[] args) {
Collection<Foo> foos = getList(FooImpl.class开发者_Go百科);
}
}
On the line where foos
is declared, I'm getting "Incompatible types. Required: Collection<Foo>, found: Collection<FooImpl>
" error. Any idea why?
Try this :
Collection<Foo> foos = Main.<Foo>getList(FooImpl.class);
When you create your getList()
method, it says that it will be Typed with T. And it also says that it will need a parameter of a subtype of T (a class of subtype of T to be precise).
As you never specify what will T be, getList suppose that it will be FooImpl
so getList()
returns a Collection of FooImpl
.
With the solution I gave you, you specify that T is Foo
, so the parameter will need to be a subtype of Foo
. FooImpl
for example.
Resources :
- JLS - Generic methods
Because it is returning a collection of FooImpl
while you like it to return a collection of its supertype. You need to define that a bit more explicitly:
public class FooImpl implements Foo { /* ... */ }
public class Main {
public static <S, T extends S> Collection<S> getList(Class<T> itemClass) { /* ... */ }
public static void main(String[] args) {
Collection<Foo> foos = getList(FooImpl.class);
}
}
Update: I had to mention that there's a JLS/javac bug related to this which caused it not to compile when using "plain vanilla" javac. See also javac bug 6369605, JLS bug 6369608 and this related question. It works fine in Eclipe however.
If you insist in using the javac over Eclipse, then your safest bet until the Java guys get it fixed is indeed to manually force the return type in the method call as demonstrated by Colin Hebert.
change getList
return type to Collection<? extends T>
FooImpl is instance of a Foo
But
Collection<FooImpl>
is NOT instance of Collection<Foo>
I agree with BaluC's answer.
Just for basic understanding of "extends" in generics check section The "extends" Wildcard Boundary
when using a wildcard with an upper bound it is not safe to write to the List. After all, a Car is always a Vehicle, but a Vehicle is not always a Car.
精彩评论