开发者

Incorrect generic type reported -- why?

开发者 https://www.devze.com 2023-01-14 13:11 出处:网络
Why doesn\'t this work? public class FooImpl implements Foo { /* ... */ } public class Main { public static <T> Collection<T> getList(Class<? extends T> itemClass) { /* ... */ }

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消