Assuming I have the following classes in an application:
A base class:
public abstract class Animal {}
A subclass
public class Dog extends Animal {
public void bark() {
System.out.println("woof");
}
}
A class from a third party library:
public class ThirdPartyLibrary /* *cough* Hibernate *cough* */{
public List find() {
return new ArrayList() {
// fetched from the db in the actual app of course
{
add(new Dog());
add(new Dog());
add(new Dog());
}
};
}
}
And a utility class:
public class Util {
public <E extends Animal> E findUnique(List<E> animals) {
return animals.isEmpty() ? null : animals.get(0);
}
/**
* @param args
*/
public static void main(String[] args) {
Dog d = new Util().findUnique(new ThirdPartyLibrary().find());
d.bark();
}
}
The eclipse compiler issues the following warnings:
- Type safety: The expression of type List needs unchecked conve开发者_开发知识库rsion to conform to List
- Type safety: Unchecked invocation findUnique(List) of the generic method findUnique(List) of type Util
But the build fails when compiling with Sun's javac with the error:
incompatible types
[javac] found : Animal
[javac] required: Dog
[javac] Dog d = new Util().findUnique(new ThirdPartyLibrary().find());
[javac] ^
Is there something else I can do to make this code compile in javac, apart from an explicit cast to (List<Dog>)
before the call to findUnique?
No, there's nothing else you can do, and you must have something fishy going on in Eclipse, because Eclipse wouldn't be able to compile that (as Java code), either. Since the list you pass to findUnique() is a raw type, the compiler can't determine what the E
should be in public <E extends Animal> E findUnique(List<E> animals)
. Therefore E
essentially becomes ?
, and what you're trying to do is basically this:
List<? extends Animal> l = new ArrayList<Animal>();
Dog dog = l.get(0);
It should be obvious that that can never work. The only way to get close to making this work is to add a method argument that makes E
have a distinct value. Something like this would work:
public <E extends Animal> E findUnique(List animals, Class<E> type) {
return animals.isEmpty() ? null : (E) animals.get(0);
}
精彩评论