Java/J2EE/JDO

Материал из Java эксперт
Перейти к: навигация, поиск

Contains static methods related to Java and JDO type conversions

   <source lang="java">
 

/*

* Copyright 2005 (C) TJDO.
* All rights reserved.
*
* This software is distributed under the terms of the TJDO License version 1.0.
* See the terms of the TJDO License in the documentation provided with this software.
*
* $Id: Types.java,v 1.1 2005/12/13 20:46:16 jackknifebarber Exp $
*/

import java.math.BigDecimal; import java.math.BigInteger; import java.util.HashMap;

/**

* Contains static methods related to Java and JDO type conversions.
*
* @author 
* @version $Revision: 1.1 $
*/

public final class Types {

   private Types()
   {
   }
   private static final HashMap WRAPPERS_BY_PRIMITIVE = new HashMap(9);
   private static final HashMap PRIMITIVES_BY_WRAPPER = new HashMap(9);
   static
   {
       WRAPPERS_BY_PRIMITIVE.put(Boolean.TYPE,   Boolean.class);
       WRAPPERS_BY_PRIMITIVE.put(Byte.TYPE,      Byte.class);
       WRAPPERS_BY_PRIMITIVE.put(Character.TYPE, Character.class);
       WRAPPERS_BY_PRIMITIVE.put(Short.TYPE,     Short.class);
       WRAPPERS_BY_PRIMITIVE.put(Integer.TYPE,   Integer.class);
       WRAPPERS_BY_PRIMITIVE.put(Long.TYPE,      Long.class);
       WRAPPERS_BY_PRIMITIVE.put(Float.TYPE,     Float.class);
       WRAPPERS_BY_PRIMITIVE.put(Double.TYPE,    Double.class);
       WRAPPERS_BY_PRIMITIVE.put(Void.TYPE,      Void.class);
       PRIMITIVES_BY_WRAPPER.put(Boolean.class,   Boolean.TYPE);
       PRIMITIVES_BY_WRAPPER.put(Byte.class,      Byte.TYPE);
       PRIMITIVES_BY_WRAPPER.put(Character.class, Character.TYPE);
       PRIMITIVES_BY_WRAPPER.put(Short.class,     Short.TYPE);
       PRIMITIVES_BY_WRAPPER.put(Integer.class,   Integer.TYPE);
       PRIMITIVES_BY_WRAPPER.put(Long.class,      Long.TYPE);
       PRIMITIVES_BY_WRAPPER.put(Float.class,     Float.TYPE);
       PRIMITIVES_BY_WRAPPER.put(Double.class,    Double.TYPE);
       PRIMITIVES_BY_WRAPPER.put(Void.class,      Void.TYPE);
   }
   /**
    * Performs a boxing conversion, if applicable.
    * If the type is a Java primitive type it"s equivalent wrapper class is
    * returned.
    * Otherwise the type itself is returned.
    *
    * @param c
    *      the type to be boxed, or 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); } } </source>