假设有两个类,即Pet
和Dog
。 Pet
类是Dog
类的超类。
Ques01:
当我编码如下时,发生编译错误:Type mismatch: cannot convert from Class<capture#2-of ? super Dog> to Class<Pet>
Class<Pet> c1 = Dog.class.getSuperclass();
必须是这样的:
Class<? super Dog> c2 = Dog.class.getSuperclass();
此外,当我使用c2.newInstance()
时,它只返回Object
个实例。为什么我不能得到Class Instance
class Pet
?
Ques02:
当我System.out c2.getName()
时,它会输出"pet"
!所以c2只是得到了我想要的信息。
我真的很困惑。任何人都可以提供帮助吗?非常感谢!
答案 0 :(得分:2)
Java中的reflexion API比泛型更老。 RTTI中的一些方法反映了这一点。
此外,RTTI是运行时功能,而泛型是编译功能。有时,编译器没有足够的信息来检查运行时类型是否正确。
但是,例如,您的newInstance
示例无效。
public class Test {
class Pet {}
class Dog extends Pet {}
public static void main(String[] args) throws Exception {
Class<Dog> dogClass = Dog.class;
Dog dog = dogClass.newInstance();
}
}
编译没有问题,因为在Class<T>
上方法声明为T newInstance()
如果我们采用getSuperClass()
示例,您必须先了解编译器不知道getSuperClass()
的作用。它只查看方法声明。这就是为什么它不知道返回的类实际上是Pet
。它只是将变量的类型与getSuperClass
返回的对象的类型进行比较。变量是Class<Pet>
,返回的对象是Class<? super Dog>
,这是不一样的。编译器不模拟getSuperClass
实现,也不知道返回的确切对象。
答案 1 :(得分:0)
一篇文章中有太多问题......
这里的一般答案是遗留和向后兼容性。泛型已经在1.5版本中引入了java。从版本1.0开始,方法getSuperClass()
存在于java中。 java创建者无法破坏与旧版本的兼容性,因此他们没有更改其原型。这就是为什么你必须将Dog.class.getSuperclass();
转换为Class<? super Dog>
或类似的东西。
同样关于newInstance()
,遗憾的是,它会在创建“正确”实例时返回普通对象。所以你也必须在这种情况下施展。因此getName()
返回正确的类名:类确实是Pet
。