我有一个类型的变量
Pair<String, Class<?>> test;
我正试图这样创建它:
Class<? extends Animal> animal = Tiger.class;
test = Pair.create("tiger", animal);
代码给了我"不兼容类型"(在创建与动物配对时)。尽管可变测试定义允许任何类型的类别,动物定义任何子类别动物的边界,这比原始定义更严格。那么这个作业不应该起作用吗?
Tiger
是Animal
的亚型,但Class<Tiger>
是而不是Class<Animal>
的亚型。Class<Tiger>
和Class<Animal>
的父代都是Class<?>
。
类似地,Pair<String, Class<? extends Animal>>
不是Pair<String, Class<?>>
的子类型,它们实际上是不同的对象,即使Class<? extends Animal>>
是Class<?>
的子类型。
为了更容易理解,可以从集合的角度来考虑它:如果你有一个Pair<String, List<?>>
,并且你给它分配了一个CCD13;然后您就可以将CCD_ 14添加到列表中。http://ideone.com/dcXnWs
在Java8中,您的代码可以工作http://ideone.com/AkK7Zv;老实说,我不确定编译器还做了什么(仍然需要深入研究新功能)。无论如何,正如您所看到的,以下示例的编译器错误是很有解释性的:
-
Java8:http://ideone.com/ZRGbyr
error: incompatible types: List<Class<? extends Animal>> cannot be converted to List<Class<?>>
-
Java7:http://ideone.com/dcXnWs(相同代码)
error: incompatible types
它在Java 8中工作的可能解释(它改进了类型推断):
public static class Pair<A, B> {
public static <A, B> Pair<A, B> create(A a, B b) {
return new Pair<A, B>();
}
}
public static class Animal {}
public static class Tiger extends Animal {}
public static final void main(final String[] args) {
Class<? extends Animal> animal = Tiger.class;
Pair<String, Class<?>> test = Pair.create("tiger", animal);
}
根据Java泛型子类型规则:
- 确实:
Class<? extends Animal> extends Class<?>
- 错误的是:
Pair<String, Class<? extends Animal>> extends Pair<String, Class<?>>
因为2。它在Java7中不起作用,但Java8使用1.:
Pair<String, Class<?>> test = Pair.create("tiger", animal);
Java 8推断出参数a的类型为String
,参数b的类型为Class<?>
。因为1。如果为true,则可以将第二个参数强制转换为Class<?>
,然后CCD_21适合变量test
的类型。
因此,因为它可以在将单个参数传递给方法之前强制转换它,所以它不必强制转换返回的结果(这是不可能的)。