Class Generics的类型不匹配

Hen*_*y B 20 java generics

我有以下不能编译的代码,虽然有一种方法可以使它编译,我想了解它为什么不编译.有人可以告诉我具体为什么我收到错误信息,我会在最后发布吗?

public class Test {
    public static void main(String args[]) {
        Test t = new Test();
        t.testT(null);
    }

    public <T extends Test> void testT(Class<T> type) {
        Class<T> testType = type == null ? Test.class : type; //Error here
        System.out.println(testType);
    }
}
Run Code Online (Sandbox Code Playgroud)

Type mismatch: cannot convert from Class<capture#1-of ? extends Test> to Class<T>

通过投射Test.classClass<T>这个编译与Unchecked cast警告并完美运行.

laz*_*laz 23

原因是Test.class的类型为Class <Test>.您不能将Class <Test>类型的引用分配给Class <T>类型的变量,因为它们不是同一个东西.但是,这有效:

Class<? extends Test> testType = type == null ? Test.class : type;
Run Code Online (Sandbox Code Playgroud)

通配符允许将Class <T>和Class <Test>引用分配给testType.

Angelika Langer Java Generics FAQ中有大量有关Java泛型行为的信息.我将根据那里使用Number类heirarchy Java的核心API的一些信息提供一个示例.

请考虑以下方法:

public <T extends Number> void testNumber(final Class<T> type)
Run Code Online (Sandbox Code Playgroud)

这是为了允许以下语句成功编译:

testNumber(Integer.class);
testNumber(Number.class);
Run Code Online (Sandbox Code Playgroud)

但以下内容无法编译:

testNumber(String.class);
Run Code Online (Sandbox Code Playgroud)

现在考虑以下陈述:

Class<Number> numberClass = Number.class;
Class<Integer> integerClass = numberClass;
Run Code Online (Sandbox Code Playgroud)

第二行无法编译并产生此错误Type mismatch: cannot convert from Class<Number> to Class<Integer>.但Integer延伸Number,为什么它会失败?查看以下两个语句,了解原因:

Number anumber = new Long(0);
Integer another = anumber;
Run Code Online (Sandbox Code Playgroud)

很容易理解第二行为什么不在这里编译.您无法将实例分配给Number类型变量,Integer因为无法保证Number实例是兼容类型.在这个例子中,Number实际上是a Long,当然不能分配给Integer.实际上,错误也是类型不匹配:Type mismatch: cannot convert from Number to Integer.

规则是不能将实例分配给作为实例类型的子类的变量,因为不能保证它是兼容的.

泛型以类似的方式表现.在泛型方法签名中,T只是一个占位符来指示方法允许编译器的内容.当编译器遇到testNumber(Integer.class)它时,它基本上替换TInteger.

通配符增加了额外的灵活性,如下所示:

Class<? extends Number> wildcard = numberClass;
Run Code Online (Sandbox Code Playgroud)

因为Class<? extends Number>指示任何类型Number或其子类Number是完全合法的并且在许多情况下可能有用.