Exemplo n.º 1
0
 /*non-public*/
 static boolean canConvert(Class<?> src, Class<?> dst) {
   // short-circuit a few cases:
   if (src == dst || dst == Object.class) return true;
   // the remainder of this logic is documented in MethodHandle.asType
   if (src.isPrimitive()) {
     // can force void to an explicit null, a la reflect.Method.invoke
     // can also force void to a primitive zero, by analogy
     if (src == void.class) return true; // or !dst.isPrimitive()?
     Wrapper sw = Wrapper.forPrimitiveType(src);
     if (dst.isPrimitive()) {
       // P->P must widen
       return Wrapper.forPrimitiveType(dst).isConvertibleFrom(sw);
     } else {
       // P->R must box and widen
       return dst.isAssignableFrom(sw.wrapperType());
     }
   } else if (dst.isPrimitive()) {
     // any value can be dropped
     if (dst == void.class) return true;
     Wrapper dw = Wrapper.forPrimitiveType(dst);
     // R->P must be able to unbox (from a dynamically chosen type) and widen
     // For example:
     //   Byte/Number/Comparable/Object -> dw:Byte -> byte.
     //   Character/Comparable/Object -> dw:Character -> char
     //   Boolean/Comparable/Object -> dw:Boolean -> boolean
     // This means that dw must be cast-compatible with src.
     if (src.isAssignableFrom(dw.wrapperType())) {
       return true;
     }
     // The above does not work if the source reference is strongly typed
     // to a wrapper whose primitive must be widened.  For example:
     //   Byte -> unbox:byte -> short/int/long/float/double
     //   Character -> unbox:char -> int/long/float/double
     if (Wrapper.isWrapperType(src) && dw.isConvertibleFrom(Wrapper.forWrapperType(src))) {
       // can unbox from src and then widen to dst
       return true;
     }
     // We have already covered cases which arise due to runtime unboxing
     // of a reference type which covers several wrapper types:
     //   Object -> cast:Integer -> unbox:int -> long/float/double
     //   Serializable -> cast:Byte -> unbox:byte -> byte/short/int/long/float/double
     // An marginal case is Number -> dw:Character -> char, which would be OK if there were a
     // subclass of Number which wraps a value that can convert to char.
     // Since there is none, we don't need an extra check here to cover char or boolean.
     return false;
   } else {
     // R->R always works, since null is always valid dynamically
     return true;
   }
 }
Exemplo n.º 2
0
 private static int ftypeKind(Class<?> ftype) {
   if (ftype.isPrimitive()) return Wrapper.forPrimitiveType(ftype).ordinal();
   else if (VerifyType.isNullReferenceConversion(Object.class, ftype)) return FT_UNCHECKED_REF;
   else return FT_CHECKED_REF;
 }