Class Literal vs Class.forname + Java Generics

时间:2012-06-30 09:30:59

标签: java generics rtti

在下面的代码片段中,为什么1不会产生运行时异常,因为我正在尝试强制转换Class> B>到班级> A>?

package example;

Class A {
   public A() {
   }
}

Class B extends A {
   public B() {
   }
}

public static void main() {

    Class<A> c = null;

    //1. Does not produce exception at run-time even though I cast Class<B> to Class<A>
    try {
        c = (Class<A>) Class.forName("example.B");
    } catch (ClassNotFoundException e) {
    }

    //2. Compile time error: Cannot Cast Class<B> to Class<A>
    c = (Class<A>) B.class; //Error
}

3 个答案:

答案 0 :(得分:3)

Class.forName()返回Class<?>,大致相当于Class(没有泛型)。

如果你在中间添加另一个非通用的强制转换,第二个版本也会编译:

c = (Class<A>)(Class) B.class; // compiles

但是,这可能不对,因此编译器可以避免此错误。在第一个版本中,它无法做到这一点。

答案 1 :(得分:1)

因为泛型只是由编译器强制执行而不是java虚拟机。您可以这样思考,在编译期间由编译器清除。 Java泛型以这种方式实现,以便与早期的Java版本向后兼容。

答案 2 :(得分:1)

Java泛型是通过擦除实现的,这意味着在编译时检查泛型,但在运行时不可用。这允许带有泛型的java代码向后兼容1.5之前的代码。

相关问题