为什么隐式转换在反射投射抛出异常时有效?

时间:2013-07-11 14:59:29

标签: java reflection casting autoboxing

假设有以下代码:

@SuppressWarnings("unchecked")
public static  <T> T implicitCaster(Class<T> cls, Object o) {
    return (T) o;
}

public static <T> T reflectionCaster(Class<T> cls, Object o) {
    return cls.cast(o);
}

代码在两种情况下都按预期工作,但在基元中有以下异常:

public static void main(String[] args) {
    System.out.println(implicitCaster(int.class, 42));
    System.out.println(reflectionCaster(int.class, 42));
}

第一个调用按预期工作,但第二个调用抛出java.lang.ClassCastException

这是一个不考虑自动装箱的角落案例吗?或者在这种情况下,反射铸造是否不可能提供自动装箱? 或者是否有其他原因导致这种不一致?

编辑:调用此代码按预期工作:

public static void main(String[] args) {
    System.out.println(implicitCaster(Integer.class, 42));
    System.out.println(reflectionCaster(Integer.class, 42));
}

1 个答案:

答案 0 :(得分:3)

这是因为类型擦除而发生的。

在运行时,不存在泛型类型参数 将对象转换为泛型类型参数无效。 (这就是为什么你得到未经检查的演员警告)

因此,您的第一行代码会自动将42传递给Object以传递给该方法。
然后该函数返回Object,传递给System.out.println


您的第二个电话会调用cast基元类型的int方法 这会引发异常,因为对象无法转换为基本类型。 (自动装箱是一个纯粹的编译时功能,所以没有帮助)

cast() checks isInstance()验证投射有效时会发生错误。

isInstance() say的文档:

  

具体来说,如果此Class对象表示声明的类,则如果指定的Object参数是所表示的类(或其任何子类)的实例,则此方法返回true;否则返回false。如果此Class对象表示数组类,则如果可以通过标识转换或扩展引用转换将指定的Object参数转换为数组类的对象,则此方法返回true;否则返回false。如果此Class对象表示接口,则如果指定Object参数的类或任何超类实现此接口,则此方法返回true;否则返回true。否则返回false。 如果此Class对象表示基本类型,则此方法返回false。

(强调补充)


您的编辑有效,因为您不再使用原始类型 在这两种情况下,编译器都会自动对象42,以便它可以作为对象传递。

与以前一样,第一次通话无效 第二个调用验证盒装整数实际上是Integer类的实例,然后返回它。