null
*
* @return
* The boxed equivalent, or the type itself if not applicable.
* null
is returned if the argument was null.
*/
public static Class box(Class c)
{
Class boxed = (Class)WRAPPERS_BY_PRIMITIVE.get(c);
return boxed == null ? c : boxed;
}
/**
* Performs an unboxing conversion, if applicable.
* If the type is a Java primitive wrapper class it's equivalent primitive
* type is returned.
* Otherwise the type itself is returned.
*
* @param c
* the type to be unboxed, or null
*
* @return
* The unboxed equivalent, or the type itself if not applicable.
* null
is returned if the argument was null.
*/
public static Class unbox(Class c)
{
Class unboxed = (Class)PRIMITIVES_BY_WRAPPER.get(c);
return unboxed == null ? c : unboxed;
}
/**
* Performs a boxing conversion on multiple classes.
* The returned array contains the results of calling {@link #box(Class)}
* on every class in the argument array.
*
* @param c
* the types to be boxed
*
* @return
* the boxed equivalent of all the types in c
*/
public static Class[] box(Class[] c)
{
int n = c.length;
Class[] boxed = new Class[n];
for (int i = 0; i < n; ++i)
boxed[i] = box(c[i]);
return boxed;
}
/**
* Performs an unboxing conversion on multiple classes.
* The returned array contains the results of calling {@link #unbox(Class)}
* on every class in the argument array.
*
* @param c
* the types to be unboxed
*
* @return
* the unboxed equivalent of all the types in c
*/
public static Class[] unbox(Class[] c)
{
int n = c.length;
Class[] unboxed = new Class[n];
for (int i = 0; i < n; ++i)
unboxed[i] = unbox(c[i]);
return unboxed;
}
/**
* Tests if a set of parameters types are all assignable from a given set of
* argument types.
* Returns true iff the number of types match and each parameter type is
* assignable from its corresponding argument type.
* "Assignable" is defined by Class.isAssignableFrom()
.
*
* All classes in the parameter type array and the argument type array must
* already be boxed.
*
* @param boxedParamTypes
* the parameter types
* @param boxedArgTypes
* the argument types
*
* @return
* true
if the all the parameter types are assignable from
* the argument types.
*/
public static boolean areAssignableFrom(Class[] boxedParamTypes, Class[] boxedArgTypes)
{
int n = boxedParamTypes.length;
if (n != boxedArgTypes.length)
return false;
for (int i = 0; i < n; ++i)
{
if (!boxedParamTypes[i].isAssignableFrom(boxedArgTypes[i]))
return false;
}
return true;
}
/**
* Performs unary numeric promotion on the given type.
* Unary numeric promotion is as defined in §5.6.1 of the Java Language
* Specification.
*
* @param operandType
* the type to be promoted, or null
*
* @return
* The promoted type, or null
if the argument was null.
*/
public static Class unaryNumericPromotion(Class operandType)
{
operandType = box(operandType);
if (operandType == Byte.class || operandType == Character.class || operandType == Short.class)
return Integer.class;
else
return operandType;
}
/**
* Performs binary numeric promotion on a set of input types.
* Binary numeric promotion is as defined in §14.6.2 of the JDO 2.0
* spec.
*
* @param types
* The input types to be promoted. If more than two types are present
* then the first two are promoted, then the promoted type and the
* third type are promoted, and so on for all the types.
*
* @return
* The promoted type. Returns null
if the input array
* is empty. Returns the first type if the input array has only one
* type.
*
* @exception IllegalArgumentException
* if any argument type is not a subclass of java.lang.Number
*/
public static Class binaryNumericPromotion(Class[] types)
{
Class promoted = null;
int n = types.length;
if (n > 0)
promoted = types[0];
for (int i = 1; i < n; ++i)
promoted = binaryNumericPromotion(promoted, types[i]);
return promoted;
}
/**
* Performs binary numeric promotion on a pair of types.
* Binary numeric promotion is as defined in §14.6.2 of the JDO 2.0
* spec.
*
* @param operand1Type
* the first type in the pair.
* @param operand2Type
* the other type in the pair.
*
* @return
* The promoted type.
*
* @exception IllegalArgumentException
* if either argument type is not a subclass of java.lang.Number
*/
public static Class binaryNumericPromotion(Class operand1Type, Class operand2Type)
{
operand1Type = box(operand1Type);
operand2Type = box(operand2Type);
if (operand1Type == BigDecimal.class || operand2Type == BigDecimal.class)
return BigDecimal.class;
if (isBigIntegerVsFloating(operand1Type, operand2Type) || isBigIntegerVsFloating(operand2Type, operand1Type))
return BigDecimal.class;
if (operand1Type == BigInteger.class || operand2Type == BigInteger.class)
return BigInteger.class;
if (operand1Type == Double.class || operand2Type == Double.class)
return Double.class;
if (operand1Type == Float.class || operand2Type == Float.class)
return Float.class;
if (operand1Type == Long.class || operand2Type == Long.class)
return Long.class;
if (!Number.class.isAssignableFrom(operand1Type) || !Number.class.isAssignableFrom(operand2Type))
throw new IllegalArgumentException("No defined numeric promotion for operands of type " + operand1Type.getName() + " and " + operand2Type.getName());
return Integer.class;
}
private static boolean isBigIntegerVsFloating(Class c1, Class c2)
{
return c1 == BigInteger.class && (c2 == Float.class || c2 == Double.class);
}
}