Java Reflection Constructor Get getConstructor(Class cls, Object... args)

Here you can find the source of getConstructor(Class cls, Object... args)

Description

Retrieve the constructor of a class for given argument values.

License

Apache License

Parameter

Parameter Description
cls class to retrieve the constructor from
args argument values
T type to retrieve the constructor from

Exception

Parameter Description
NoSuchMethodException if a matching method is not found.

Return

matching constructor for given argument values

Declaration

public static <T> Constructor<T> getConstructor(Class<T> cls, Object... args) throws NoSuchMethodException 

Method Source Code

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

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

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<>();

    /**// w  ww.  ja  va 2s  .  c  o m
     * 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;
    }

    /**
     * Get the field value even if not accessible.
     *
     * @param field field to get
     * @param obj   instance to get
     * @return field value
     * @throws IllegalAccessException if this {@code Field} object
     *                                is enforcing Java language access control and the underlying
     *                                field is inaccessible.
     * @see Field#get(Object)
     */
    public static Object get(Field field, Object obj) throws IllegalAccessException {
        boolean accessible = field.isAccessible();
        if (accessible) {
            return field.get(obj);
        }
        field.setAccessible(true);
        try {
            return field.get(obj);
        } finally {
            field.setAccessible(accessible);
        }
    }
}

Related

  1. getConstructor(Class clazz)
  2. getConstructor(Class clazz, Class... parameterTypes)
  3. getConstructor(Class clazz, Class[] expectedTypes)
  4. getConstructor(Class cls, Class... parameterClses)
  5. getConstructor(Class cls, Class[] args)
  6. getConstructor(Class instanceType)
  7. getConstructor(Class targetClass, Class... parameterTypes)
  8. getConstructor(Class type, Class... parameterTypes)
  9. getConstructor(Class type, Class[] parameterTypes)