通用类型分配表示不兼容的类型以进行更严格的分配

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 动物的边界,这比原来的更严格。那么这个作业不应该工作吗?

TigerAnimal 的子类型,但 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;老实说,我不确定编译器还做了什么(仍然需要研究新特性)。无论如何,如您所见,以下示例的编译器错误非常具有解释性:

它在 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:

  1. 这是真的:Class<? extends Animal> extends Class<?>
  2. 错误的是: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.

因为它可以在将单个参数传递给方法之前对其进行转换,所以它不必转换返回的结果(这是不可能的)。