假设我在应用程序中有以下类:
一个基类:
public abstract class Animal {}
Run Code Online (Sandbox Code Playgroud)
一个子类
public class Dog extends Animal {
public void bark() {
System.out.println("woof");
}
}
Run Code Online (Sandbox Code Playgroud)
来自第三方库的类:
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());
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
还有一个实用程序类:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
eclipse 编译器发出以下警告:
- 类型安全:List 类型的表达式需要未经检查的转换才能符合 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] ^
Run Code Online (Sandbox Code Playgroud)
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?
不,您无能为力,而且您必须在 Eclipse 中进行一些可疑的操作,因为 Eclipse 也无法编译它(作为 Java 代码)。既然你传递给findUnique()是一个原始类型列表中,编译器不能确定什么E应该是public <E extends Animal> E findUnique(List<E> animals)。因此E基本上变成了?,而你要做的基本上是这样的:
List<? extends Animal> l = new ArrayList<Animal>();
Dog dog = l.get(0);
Run Code Online (Sandbox Code Playgroud)
很明显,这永远行不通。接近完成这项工作的唯一方法是添加一个E具有不同值的方法参数。像这样的事情会起作用:
public <E extends Animal> E findUnique(List animals, Class<E> type) {
return animals.isEmpty() ? null : (E) animals.get(0);
}
Run Code Online (Sandbox Code Playgroud)