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.class
为Class
,可以使用Unchecked cast
强制转换Test.class
进行编译并完美运行。
原因是Test.class的类型为Class
Class extends Test> testType = type == null ? Test.class : type;
通配符允许将Class
在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
。 但是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 extends Number> wildcard = numberClass;
因为Class extends Number>
Class extends Number>
表示Number
或子类,这是完全合法的,在许多情况下可能有用。
假设我扩展测试:
public class SubTest extends Test { public static void main(String args[]) { Test t = new Test(); t.testT(new SubTest()); } }
现在,当我调用testT
,类型参数
是SubTest
,这意味着变量testType
是Class
。 Test.class
的类型为Class
,它不能分配给Class
类型的变量。
将变量testType
声明为Class extends Test>
Class extends Test>
是正确的解决方案; 转换为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;