简体   繁体   English

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

[英]Why does implicit casting work while reflection casting throws exception?

Suppose there is the following code: 假设有以下代码:

@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);
}

The code works as expected in both cases with the following exception, found in primitives: 代码在两种情况下都按预期工作,但在基元中有以下异常:

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

The first call works as expected but the second call throws java.lang.ClassCastException . 第一个调用按预期工作,但第二个调用抛出java.lang.ClassCastException

Is this a corner case in which autoboxing was disregarded? 这是一个不考虑自动装箱的角落案例吗? Or is it impossible to provide autoboxing in this case, of reflection casting? 或者在这种情况下,反射铸造是否不可能提供自动装箱? Or is there something else causing this inconsistency? 或者是否有其他原因导致这种不一致?

Edit: calling this code works as expected: 编辑:调用此代码按预期工作:

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

This happens because of type erasure. 这是因为类型擦除。

At runtime, generic type parameters don't exist. 在运行时,不存在泛型类型参数。
Casting an object to a generic type parameter has no effect. 将对象转换为泛型类型参数无效。 (which is why you get the unchecked cast warning) (这就是为什么你得到未经检查的演员警告)

Therefore, your first line autoboxes 42 to Object to pass to the method. 因此,您的第一行自动装箱42Object传递给该方法。
The function then returns that Object , which is passed to System.out.println . 然后该函数返回该Object ,该Object将传递给System.out.println


Your second call calls the cast method of the int primitive type. 您的第二个调用调用int基本类型的cast方法。
This throws an exception, because objects cannot be casted to primitive types. 这会引发异常,因为对象无法转换为基本类型。 (auto-boxing is a purely compile-time feature, so it doesn't help) (自动装箱是一个纯粹的编译时功能,所以它没有帮助)

The error happens when cast() checks isInstance() to verify that the cast is valid. cast() 检查isInstance()以验证isInstance()转换是否有效时,会发生错误。

The docs for isInstance() say : isInstance()的文档

Specifically, if this Class object represents a declared class, this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses); 具体来说,如果此Class对象表示声明的类,则如果指定的Object参数是所表示的类(或其任何子类)的实例,则此方法返回true; it returns false otherwise. 否则返回false。 If this Class object represents an array class, this method returns true if the specified Object argument can be converted to an object of the array class by an identity conversion or by a widening reference conversion; 如果此Class对象表示数组类,则如果可以通过标识转换或扩展引用转换将指定的Object参数转换为数组类的对象,则此方法返回true; it returns false otherwise. 否则返回false。 If this Class object represents an interface, this method returns true if the class or any superclass of the specified Object argument implements this interface; 如果此Class对象表示接口,则如果指定Object参数的类或任何超类实现此接口,则此方法返回true;否则返回true。 it returns false otherwise. 否则返回false。 If this Class object represents a primitive type, this method returns false. 如果此Class对象表示基本类型,则此方法返回false。

(emphasis added) (重点补充)


Your edit works because you are no longer using a primitive type. 您的编辑有效,因为您不再使用基本类型。
In both cases, the compiler autoboxes 42 so that it can be passed as an object. 在这两种情况下,编译器都会自动装箱42以便它可以作为对象传递。

The first call, as before, has no effect. 与以前一样,第一次通话无效。
The second call verifies that the boxed integer is in fact an instance of the Integer class, then returns it. 第二个调用验证盒装整数实际上是Integer类的实例,然后返回它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM