2

假设有两个类,即PetDogPet类是类的超Dog类。

问题01:

当我如下编码时,发生编译错误: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 Instanceof class Pet

问题02:

当我 System.out 时c2.getName(),它输出"pet"!所以 c2 刚刚得到了我想要的信息。

我真的被这些弄糊涂了。任何人都可以提供任何帮助吗?非常感谢!

4

2 回答 2

2

Java 中的反射 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实现,也不知道返回的确切对象。

于 2013-04-07T13:31:29.440 回答
0

一篇文章的问题太多了......

这里的一般答案是遗留和向后兼容性。泛型已在 1.5 版中引入 java。方法getSuperClass()自 1.0 版开始存在于 java 中。java 创建者无法破坏与旧版本的兼容性,因此他们没有更改其原型。这就是为什么你必须强制Dog.class.getSuperclass();转换Class<? super Dog>或类似的东西。

不幸的是newInstance(),它在创建“正确”实例时返回普通对象也是如此。所以你也必须在这种情况下施放。因此getName()返回正确的类名:该类确实是Pet.

于 2013-04-07T13:27:41.183 回答