原因是 Test.class 属于 Class<Test> 类型。您不能将 Class<Test> 类型的引用分配给 Class<T> 类型的变量,因为它们不是同一个东西。但是,这有效:
Class<? extends Test> testType = type == null ? Test.class : type;
通配符允许将 Class<T> 和 Class<Test> 引用分配给 testType。
在Angelika Langer Java Generics FAQ中有大量关于 Java 泛型行为的信息。我将根据那里使用Number
类层次结构 Java 的核心 API 的一些信息提供一个示例。
考虑以下方法:
public <T extends Number> void testNumber(final Class<T> type)
这是为了让以下语句能够成功编译:
testNumber(Integer.class);
testNumber(Number.class);
但以下内容无法编译:
testNumber(String.class);
现在考虑这些陈述:
Class<Number> numberClass = Number.class;
Class<Integer> integerClass = numberClass;
第二行无法编译并产生此错误Type mismatch: cannot convert from Class<Number> to Class<Integer>
。但是Integer
extends Number
,那为什么会失败呢?查看接下来的两个语句以了解原因:
Number anumber = new Long(0);
Integer another = anumber;
很容易看出为什么第二行在这里没有编译。您不能将 的实例分配给Number
类型变量,Integer
因为无法保证该Number
实例是兼容类型。在此示例中,Number
实际是 a Long
,当然不能将其分配给Integer
。其实错误也是类型不匹配:Type mismatch: cannot convert from Number to Integer
.
规则是不能将实例分配给作为实例类型的子类的变量,因为不能保证是兼容的。
泛型的行为方式类似。在泛型方法签名中,T
只是一个占位符,用于指示该方法允许编译器做什么。当编译器遇到它时,testNumber(Integer.class)
它基本上替换T
为Integer
.
通配符增加了额外的灵活性,因为以下将编译:
Class<? extends Number> wildcard = numberClass;
因为Class<? extends Number>
表示任何属于 thisNumber
或其子类的类型Number
在许多情况下都是完全合法的并且可能有用。