Java Reflection Constructor Get getConstructorOptional(Class cls, Class... argsTypes)

Here you can find the source of getConstructorOptional(Class cls, Class... argsTypes)

Description

Retrieve the constructor of a class for given optional argument types.

License

Apache License

Parameter

Parameter Description
cls class to retrieve the constructor from
argsTypes argument types
T type to retrieve the constructor from

Exception

Parameter Description
NoSuchMethodException if a matching method is not found.

Return

matching constructor for given optional argument values

Declaration

public static <T> Constructor<T> getConstructorOptional(Class<T> cls, Class<?>... argsTypes)
        throws NoSuchMethodException 

Method Source Code

//package com.java2s;
//License from project: Apache License 

import java.lang.reflect.Constructor;

import java.util.Arrays;
import java.util.HashMap;

import java.util.Map;

public class Main {
    private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
    private static final Map<Class<?>, Class<?>> PRIMITIVES_TO_WRAPPERS = new HashMap<>();

    /**/*from  w ww. jav a  2s  . c o m*/
     * Retrieve the constructor of a class for given optional argument types.
     *
     * @param cls       class to retrieve the constructor from
     * @param argsTypes argument types
     * @param <T>       type to retrieve the constructor from
     * @return matching constructor for given optional argument values
     * @throws NoSuchMethodException if a matching method is not found.
     */
    public static <T> Constructor<T> getConstructorOptional(Class<T> cls, Class<?>... argsTypes)
            throws NoSuchMethodException {
        return getConstructorOptional(0, cls, argsTypes);
    }

    /**
     * Retrieve the constructor of a class for given optional argument types, considering mandatory values at the
     * beginning of the given types.
     *
     * @param mandatoryCount number of mandatory arguments at the beginning of the given arguments
     * @param cls            class to retrieve the constructor from
     * @param argsTypes      argument types
     * @param <T>            type to retrieve the constructor from
     * @return matching constructor for given optional argument values
     * @throws NoSuchMethodException if a matching method is not found.
     */
    public static <T> Constructor<T> getConstructorOptional(int mandatoryCount, Class<T> cls, Class<?>... argsTypes)
            throws NoSuchMethodException {
        while (true) {
            try {
                return getConstructor(cls, argsTypes);
            } catch (NoSuchMethodException e) {
                if (argsTypes.length == mandatoryCount) {
                    break;
                }
                argsTypes = Arrays.copyOf(argsTypes, argsTypes.length - 1);
            }
        }
        throw new NoSuchMethodException("Can't find any valid constructor.");
    }

    /**
     * Retrieve the constructor of a class for given argument values.
     *
     * @param cls  class to retrieve the constructor from
     * @param args argument values
     * @param <T>  type to retrieve the constructor from
     * @return matching constructor for given argument values
     * @throws NoSuchMethodException if a matching method is not found.
     */
    public static <T> Constructor<T> getConstructor(Class<T> cls, Object... args) throws NoSuchMethodException {
        Class<?>[] argsTypes = toClass(args);
        return getConstructor(cls, argsTypes);
    }

    /**
     * Retrieve the constructor of a class for given argument types.
     *
     * @param cls       class to retrieve the constructor from
     * @param argsTypes argument types
     * @param <T>       type to retrieve the constructor from
     * @return matching constructor for given argument values
     * @throws NoSuchMethodException if a matching method is not found.
     */
    public static <T> Constructor<T> getConstructor(Class<T> cls, Class<?>... argsTypes)
            throws NoSuchMethodException {
        if (argsTypes == null || argsTypes.length == 0) {
            return cls.getDeclaredConstructor();
        }

        try {
            return cls.getDeclaredConstructor(argsTypes);
        } catch (NoSuchMethodException e) {
            for (Constructor<?> constructor : cls.getDeclaredConstructors()) {
                if (isMatchingConstructor(constructor, argsTypes)) {
                    return (Constructor<T>) constructor;
                }
            }
            throw e;
        }
    }

    /**
     * Converts an array of {@code Object} into an array of {@code Class} objects.
     * <p>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
     */
    public static Class<?>[] toClass(Object... array) {
        if (array == null) {
            return null;
        } else if (array.length == 0) {
            return EMPTY_CLASS_ARRAY; // NOPMD MethodReturnsInternalArray
        }
        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;
    }

    private static boolean isMatchingConstructor(Constructor<?> constructor, Class<?>[] argsTypes) {
        Class<?>[] parameterTypes = constructor.getParameterTypes();
        if (parameterTypes.length != argsTypes.length) {
            return false;
        }

        boolean match = true;
        for (int i = 0; i < parameterTypes.length; i++) {
            parameterTypes[i] = wrapPrimitive(parameterTypes[i]);
            if (argsTypes[i] != null) { // NOPMD ConfusingTernary
                if (!parameterTypes[i].isAssignableFrom(argsTypes[i])) {
                    match = false;
                    break;
                }
            } else if (parameterTypes[i].isPrimitive()) {
                match = false;
                break;
            }
        }
        return match;
    }

    /**
     * Wrap given class to it's primitive class if it's matching a primitive class.
     *
     * @param clazz primitive class or not
     * @param <T>   type of class
     * @return class or primitive class
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> wrapPrimitive(Class<T> clazz) {
        return clazz.isPrimitive() ? (Class<T>) PRIMITIVES_TO_WRAPPERS.get(clazz) : clazz;
    }
}

Related

  1. getConstructorDescriptor(final Constructor c)
  2. getConstructorForArguments( java.lang.reflect.Constructor[] constructors, Object... arguments)
  3. getConstructorFromSignature(Class clazz, String cstrSig)
  4. getConstructorIfAvailable(Class clazz, Class... paramTypes)
  5. getConstructorLabel(java.lang.reflect.Constructor con)
  6. getConstructorOrFail(Class clazz, Class... argTypes)
  7. getConstructors(Class cl)
  8. getConstructors(Class infoClass)
  9. getConstructors(Class clazz)