Class Generics的类型不匹配

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

public class Test { public static void main(String args[]) { Test t = new Test(); t.testT(null); } public  void testT(Class type) { Class testType = type == null ? Test.class : type; //Error here System.out.println(testType); } } 

Type mismatch: cannot convert from Class to Class

通过将Test.classClass ,可以使用Unchecked cast强制转换Test.class进行编译并完美运行。

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

 Class testType = type == null ? Test.class : type; 

通配符允许将Class 和Class 引用分配给testType。

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

考虑以下方法:

 public  void testNumber(final Class type) 

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

 testNumber(Integer.class); testNumber(Number.class); 

但以下内容无法编译:

 testNumber(String.class); 

现在考虑以下陈述:

 Class numberClass = Number.class; Class integerClass = numberClass; 

第二行无法编译并产生此错误Type mismatch: cannot convert from Class to Class 。 但是Integer扩展了Number ,那为什么会失败呢? 看看接下来的两个陈述,看看为什么:

 Number anumber = new Long(0); Integer another = anumber; 

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

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

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

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

 Class wildcard = numberClass; 

因为Class Class表示Number或子类,这是完全合法的,在许多情况下可能有用。

假设我扩展测试:

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

现在,当我调用testT ,类型参数SubTest ,这意味着变量testTypeClassTest.class的类型为Class ,它不能分配给Class类型的变量。

将变量testType声明为Class Class是正确的解决方案; 转换为Class隐藏了一个真正的问题。

删除条件,错误更好一点……

 public class Test { public static void main(String args[]) { Test t = new Test(); t.testT(null); } public  void testT(Class type) { Class testClass = Test.class; System.out.println(testClass); } } Test.java:10: incompatible types found : java.lang.Class required: java.lang.Class Class testClass = Test.class;