/** * Adapts the return type of the method handle with {@code explicitCastArguments} when it is an * unboxing conversion. This will ensure that nulls are unwrapped to false or 0. * * @param target the target method handle * @param newType the desired new type. Note that this method does not adapt the method handle * completely to the new type, it only adapts the return type; this is allowed as per {@link * DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)}, which is * what this method is used for. * @return the method handle with adapted return type, if it required an unboxing conversion. */ private static MethodHandle unboxReturnType(final MethodHandle target, final MethodType newType) { final MethodType targetType = target.type(); final Class<?> oldReturnType = targetType.returnType(); final Class<?> newReturnType = newType.returnType(); if (TypeUtilities.isWrapperType(oldReturnType)) { if (newReturnType.isPrimitive()) { // The contract of setAutoConversionStrategy is such that the difference between newType and // targetType // can only be JLS method invocation conversions. assert TypeUtilities.isMethodInvocationConvertible(oldReturnType, newReturnType); return MethodHandles.explicitCastArguments( target, targetType.changeReturnType(newReturnType)); } } else if (oldReturnType == void.class && newReturnType == Object.class) { return MethodHandles.filterReturnValue(target, VOID_TO_OBJECT); } return target; }
private static boolean canWiden(final Class<?> type) { return TypeUtilities.isWrapperType(type) && type != Boolean.class && type != Character.class; }