假设有以下代码:
@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));
}
答案 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
类的实例,然后返回它。