/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * This is a modified version of the original Apache class.  It has had unused
 * members removed.
 */
package org.ehcache.impl.internal.classes.commonslang;

import java.util.HashMap;
import java.util.Map;

Operates on classes without using reflection.

This class handles invalid null inputs as best it can. Each method documents its behaviour in more detail.

The notion of a canonical name includes the human readable name for the type, for example int[]. The non-canonical method variants work with the JVM names, such as [I.

Since:2.0
/** * <p>Operates on classes without using reflection.</p> * * <p>This class handles invalid {@code null} inputs as best it can. * Each method documents its behaviour in more detail.</p> * * <p>The notion of a {@code canonical name} includes the human * readable name for the type, for example {@code int[]}. The * non-canonical method variants work with the JVM names, such as * {@code [I}. </p> * * @since 2.0 */
public class ClassUtils {
Maps names of primitives to their corresponding primitive Classes.
/** * Maps names of primitives to their corresponding primitive {@code Class}es. */
private static final Map<String, Class<?>> namePrimitiveMap = new HashMap<>(); static { namePrimitiveMap.put("boolean", Boolean.TYPE); namePrimitiveMap.put("byte", Byte.TYPE); namePrimitiveMap.put("char", Character.TYPE); namePrimitiveMap.put("short", Short.TYPE); namePrimitiveMap.put("int", Integer.TYPE); namePrimitiveMap.put("long", Long.TYPE); namePrimitiveMap.put("double", Double.TYPE); namePrimitiveMap.put("float", Float.TYPE); namePrimitiveMap.put("void", Void.TYPE); }
Maps primitive Classes to their corresponding wrapper Class.
/** * Maps primitive {@code Class}es to their corresponding wrapper {@code Class}. */
private static final Map<Class<?>, Class<?>> primitiveWrapperMap = new HashMap<>(); static { primitiveWrapperMap.put(Boolean.TYPE, Boolean.class); primitiveWrapperMap.put(Byte.TYPE, Byte.class); primitiveWrapperMap.put(Character.TYPE, Character.class); primitiveWrapperMap.put(Short.TYPE, Short.class); primitiveWrapperMap.put(Integer.TYPE, Integer.class); primitiveWrapperMap.put(Long.TYPE, Long.class); primitiveWrapperMap.put(Double.TYPE, Double.class); primitiveWrapperMap.put(Float.TYPE, Float.class); primitiveWrapperMap.put(Void.TYPE, Void.TYPE); }
Maps wrapper Classes to their corresponding primitive types.
/** * Maps wrapper {@code Class}es to their corresponding primitive types. */
private static final Map<Class<?>, Class<?>> wrapperPrimitiveMap = new HashMap<>(); static { for (final Map.Entry<Class<?>, Class<?>> entry : primitiveWrapperMap.entrySet()) { final Class<?> primitiveClass = entry.getKey(); final Class<?> wrapperClass = entry.getValue(); if (!primitiveClass.equals(wrapperClass)) { wrapperPrimitiveMap.put(wrapperClass, primitiveClass); } } } // Is assignable // ----------------------------------------------------------------------

Checks if an array of Classes can be assigned to another array of Classes.

This method calls isAssignable for each Class pair in the input arrays. It can be used to check if a set of arguments (the first parameter) are suitably compatible with a set of method parameter types (the second parameter).

Unlike the Class.isAssignableFrom(Class) method, this method takes into account widenings of primitive classes and nulls.

Primitive widenings allow an int to be assigned to a long, float or double. This method returns the correct result for these cases.

Null may be assigned to any reference type. This method will return true if null is passed in and the toClass is non-primitive.

Specifically, this method tests whether the type represented by the specified Class parameter can be converted to the type represented by this Class object via an identity conversion widening primitive or widening reference conversion. See The Java Language Specification, sections 5.1.1, 5.1.2 and 5.1.4 for details.

Params:
  • classArray – the array of Classes to check, may be null
  • toClassArray – the array of Classes to try to assign into, may be null
  • autoboxing – whether to use implicit autoboxing/unboxing between primitives and wrappers
Returns:true if assignment possible
/** * <p>Checks if an array of Classes can be assigned to another array of Classes.</p> * * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each * Class pair in the input arrays. It can be used to check if a set of arguments * (the first parameter) are suitably compatible with a set of method parameter types * (the second parameter).</p> * * <p>Unlike the {@link Class#isAssignableFrom(Class)} method, this * method takes into account widenings of primitive classes and * {@code null}s.</p> * * <p>Primitive widenings allow an int to be assigned to a {@code long}, * {@code float} or {@code double}. This method returns the correct * result for these cases.</p> * * <p>{@code Null} may be assigned to any reference type. This method will * return {@code true} if {@code null} is passed in and the toClass is * non-primitive.</p> * * <p>Specifically, this method tests whether the type represented by the * specified {@code Class} parameter can be converted to the type * represented by this {@code Class} object via an identity conversion * widening primitive or widening reference conversion. See * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>, * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p> * * @param classArray the array of Classes to check, may be {@code null} * @param toClassArray the array of Classes to try to assign into, may be {@code null} * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers * @return {@code true} if assignment possible */
public static boolean isAssignable(Class<?>[] classArray, Class<?>[] toClassArray, final boolean autoboxing) { if (!ArrayUtils.isSameLength(classArray, toClassArray)) { return false; } if (classArray == null) { classArray = ArrayUtils.EMPTY_CLASS_ARRAY; } if (toClassArray == null) { toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY; } for (int i = 0; i < classArray.length; i++) { if (!isAssignable(classArray[i], toClassArray[i], autoboxing)) { return false; } } return true; }

Checks if one Class can be assigned to a variable of another Class.

Unlike the Class.isAssignableFrom(Class) method, this method takes into account widenings of primitive classes and nulls.

Primitive widenings allow an int to be assigned to a long, float or double. This method returns the correct result for these cases.

Null may be assigned to any reference type. This method will return true if null is passed in and the toClass is non-primitive.

Specifically, this method tests whether the type represented by the specified Class parameter can be converted to the type represented by this Class object via an identity conversion widening primitive or widening reference conversion. See The Java Language Specification, sections 5.1.1, 5.1.2 and 5.1.4 for details.

Since Lang 3.0, this method will default behavior for calculating assignability between primitive and wrapper types corresponding to the running Java version; i.e. autoboxing will be the default behavior in VMs running Java versions > 1.5.

Params:
  • cls – the Class to check, may be null
  • toClass – the Class to try to assign into, returns false if null
Returns:true if assignment possible
/** * <p>Checks if one {@code Class} can be assigned to a variable of * another {@code Class}.</p> * * <p>Unlike the {@link Class#isAssignableFrom(Class)} method, * this method takes into account widenings of primitive classes and * {@code null}s.</p> * * <p>Primitive widenings allow an int to be assigned to a long, float or * double. This method returns the correct result for these cases.</p> * * <p>{@code Null} may be assigned to any reference type. This method * will return {@code true} if {@code null} is passed in and the * toClass is non-primitive.</p> * * <p>Specifically, this method tests whether the type represented by the * specified {@code Class} parameter can be converted to the type * represented by this {@code Class} object via an identity conversion * widening primitive or widening reference conversion. See * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>, * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p> * * <p><strong>Since Lang 3.0,</strong> this method will default behavior for * calculating assignability between primitive and wrapper types <em>corresponding * to the running Java version</em>; i.e. autoboxing will be the default * behavior in VMs running Java versions &gt; 1.5.</p> * * @param cls the Class to check, may be null * @param toClass the Class to try to assign into, returns false if null * @return {@code true} if assignment possible */
public static boolean isAssignable(final Class<?> cls, final Class<?> toClass) { return isAssignable(cls, toClass, true); }

Checks if one Class can be assigned to a variable of another Class.

Unlike the Class.isAssignableFrom(Class) method, this method takes into account widenings of primitive classes and nulls.

Primitive widenings allow an int to be assigned to a long, float or double. This method returns the correct result for these cases.

Null may be assigned to any reference type. This method will return true if null is passed in and the toClass is non-primitive.

Specifically, this method tests whether the type represented by the specified Class parameter can be converted to the type represented by this Class object via an identity conversion widening primitive or widening reference conversion. See The Java Language Specification, sections 5.1.1, 5.1.2 and 5.1.4 for details.

Params:
  • cls – the Class to check, may be null
  • toClass – the Class to try to assign into, returns false if null
  • autoboxing – whether to use implicit autoboxing/unboxing between primitives and wrappers
Returns:true if assignment possible
/** * <p>Checks if one {@code Class} can be assigned to a variable of * another {@code Class}.</p> * * <p>Unlike the {@link Class#isAssignableFrom(Class)} method, * this method takes into account widenings of primitive classes and * {@code null}s.</p> * * <p>Primitive widenings allow an int to be assigned to a long, float or * double. This method returns the correct result for these cases.</p> * * <p>{@code Null} may be assigned to any reference type. This method * will return {@code true} if {@code null} is passed in and the * toClass is non-primitive.</p> * * <p>Specifically, this method tests whether the type represented by the * specified {@code Class} parameter can be converted to the type * represented by this {@code Class} object via an identity conversion * widening primitive or widening reference conversion. See * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>, * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p> * * @param cls the Class to check, may be null * @param toClass the Class to try to assign into, returns false if null * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers * @return {@code true} if assignment possible */
public static boolean isAssignable(Class<?> cls, final Class<?> toClass, final boolean autoboxing) { if (toClass == null) { return false; } // have to check for null, as isAssignableFrom doesn't if (cls == null) { return !toClass.isPrimitive(); } //autoboxing: if (autoboxing) { if (cls.isPrimitive() && !toClass.isPrimitive()) { cls = primitiveToWrapper(cls); if (cls == null) { return false; } } if (toClass.isPrimitive() && !cls.isPrimitive()) { cls = wrapperToPrimitive(cls); if (cls == null) { return false; } } } if (cls.equals(toClass)) { return true; } if (cls.isPrimitive()) { if (!toClass.isPrimitive()) { return false; } if (Integer.TYPE.equals(cls)) { return Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Long.TYPE.equals(cls)) { return Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Boolean.TYPE.equals(cls)) { return false; } if (Double.TYPE.equals(cls)) { return false; } if (Float.TYPE.equals(cls)) { return Double.TYPE.equals(toClass); } if (Character.TYPE.equals(cls)) { return Integer.TYPE.equals(toClass) || Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Short.TYPE.equals(cls)) { return Integer.TYPE.equals(toClass) || Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Byte.TYPE.equals(cls)) { return Short.TYPE.equals(toClass) || Integer.TYPE.equals(toClass) || Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } // should never get here return false; } return toClass.isAssignableFrom(cls); }

Converts the specified primitive Class object to its corresponding wrapper Class object.

NOTE: From v2.2, this method handles Void.TYPE, returning Void.TYPE.

Params:
  • cls – the class to convert, may be null
Returns:the wrapper class for cls or cls if cls is not a primitive. null if null input.
Since:2.1
/** * <p>Converts the specified primitive Class object to its corresponding * wrapper Class object.</p> * * <p>NOTE: From v2.2, this method handles {@code Void.TYPE}, * returning {@code Void.TYPE}.</p> * * @param cls the class to convert, may be null * @return the wrapper class for {@code cls} or {@code cls} if * {@code cls} is not a primitive. {@code null} if null input. * @since 2.1 */
public static Class<?> primitiveToWrapper(final Class<?> cls) { Class<?> convertedClass = cls; if (cls != null && cls.isPrimitive()) { convertedClass = primitiveWrapperMap.get(cls); } return convertedClass; }

Converts the specified wrapper class to its corresponding primitive class.

This method is the counter part of primitiveToWrapper(). If the passed in class is a wrapper class for a primitive type, this primitive type will be returned (e.g. Integer.TYPE for Integer.class). For other classes, or if the parameter is null, the return value is null.

Params:
  • cls – the class to convert, may be null
See Also:
Returns:the corresponding primitive type if cls is a wrapper class, null otherwise
Since:2.4
/** * <p>Converts the specified wrapper class to its corresponding primitive * class.</p> * * <p>This method is the counter part of {@code primitiveToWrapper()}. * If the passed in class is a wrapper class for a primitive type, this * primitive type will be returned (e.g. {@code Integer.TYPE} for * {@code Integer.class}). For other classes, or if the parameter is * <b>null</b>, the return value is <b>null</b>.</p> * * @param cls the class to convert, may be <b>null</b> * @return the corresponding primitive type if {@code cls} is a * wrapper class, <b>null</b> otherwise * @see #primitiveToWrapper(Class) * @since 2.4 */
public static Class<?> wrapperToPrimitive(final Class<?> cls) { return wrapperPrimitiveMap.get(cls); } // ----------------------------------------------------------------------

Converts an array of Object in to an array of Class objects. If any of these objects is null, a null element will be inserted into the array.

This method returns null for a null input array.

Params:
  • array – an Object array
Returns:a Class array, null if null array input
Since:2.4
/** * <p>Converts an array of {@code Object} in to an array of {@code Class} objects. * If any of these objects is null, a null element will be inserted into the array.</p> * * <p>This method returns {@code null} for a {@code null} input array.</p> * * @param array an {@code Object} array * @return a {@code Class} array, {@code null} if null array input * @since 2.4 */
public static Class<?>[] toClass(final Object... array) { if (array == null) { return null; } else if (array.length == 0) { return ArrayUtils.EMPTY_CLASS_ARRAY; } final Class<?>[] classes = new Class<?>[array.length]; for (int i = 0; i < array.length; i++) { classes[i] = array[i] == null ? null : array[i].getClass(); } return classes; } }