通用类型分配表示不兼容的类型以进行更严格的分配
Generic type assignment says incompatible type for more restrictive assignment
我有一个以下类型的变量
Pair<String, Class<?>> test;
我正在尝试这样创建它:
Class<? extends Animal> animal = Tiger.class;
test = Pair.create("tiger", animal);
代码给了我 "Incompatible types"(在创建 Pair with animal 时)。虽然变量测试定义允许 class 任何类型和 animal 定义任何 child class 动物的边界,这比原来的更严格。那么这个作业不应该工作吗?
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<?>>
,你给它分配了一个Pair<String, List<? extends Number>>
;然后您可以将 String
添加到列表中。 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 Generics Subtyping Rules:
- 这是真的:
Class<? extends Animal> extends Class<?>
- 错误的是:
Pair<String, Class<? extends Animal>> extends Pair<String, Class<?>>
因为 2. 它在 Java 7 中不起作用,但是 Java 8 利用 1.:
Pair<String, Class<?>> test = Pair.create("tiger", animal);
Java 8 推断参数 a 的类型为 String
,参数 b 的类型为 Class<?>
。因为 1. 为真,它可以将第二个参数转换为 Class<?>
,然后适合变量的类型 test
.
因为它可以在将单个参数传递给方法之前对其进行转换,所以它不必转换返回的结果(这是不可能的)。
我有一个以下类型的变量
Pair<String, Class<?>> test;
我正在尝试这样创建它:
Class<? extends Animal> animal = Tiger.class;
test = Pair.create("tiger", animal);
代码给了我 "Incompatible types"(在创建 Pair with animal 时)。虽然变量测试定义允许 class 任何类型和 animal 定义任何 child class 动物的边界,这比原来的更严格。那么这个作业不应该工作吗?
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<?>>
,你给它分配了一个Pair<String, List<? extends Number>>
;然后您可以将 String
添加到列表中。 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 Generics Subtyping Rules:
- 这是真的:
Class<? extends Animal> extends Class<?>
- 错误的是:
Pair<String, Class<? extends Animal>> extends Pair<String, Class<?>>
因为 2. 它在 Java 7 中不起作用,但是 Java 8 利用 1.:
Pair<String, Class<?>> test = Pair.create("tiger", animal);
Java 8 推断参数 a 的类型为 String
,参数 b 的类型为 Class<?>
。因为 1. 为真,它可以将第二个参数转换为 Class<?>
,然后适合变量的类型 test
.
因为它可以在将单个参数传递给方法之前对其进行转换,所以它不必转换返回的结果(这是不可能的)。