Find an accessible constructor with compatible parameters. - Java Reflection

Java examples for Reflection:Constructor

Description

Find an accessible constructor with compatible parameters.

Demo Code

/*/*from  ww  w.j  ava  2 s  .c o  m*/
 * Copyright (c) 2007-2016 AREasy Runtime
 *
 * This library, AREasy Runtime and API for BMC Remedy AR System, is free software ("Licensed Software");
 * you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either version 2.1 of the License,
 * or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * including but not limited to, the implied warranty of MERCHANTABILITY, NONINFRINGEMENT,
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 */
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

public class Main{
    /**
     * <p>Find an accessible constructor with compatible parameters.
     * Compatible parameters mean that every method parameter is assignable from
     * the given parameters. In other words, it finds constructor that will take
     * the parameters given.</p>
     * <p/>
     * <p>First it checks if there is constructor matching the exact signature.
     * If no such, all the constructors of the class are tested if their signatures
     * are assignment compatible with the parameter types.
     * The first matching constructor is returned.</p>
     *
     * @param clazz          find constructor for this class
     * @param parameterTypes find method with compatible parameters
     * @return a valid Constructor object. If there's no matching constructor, returns <code>null</code>.
     */
    private static Constructor getMatchingAccessibleConstructor(
            Class clazz, Class[] parameterTypes) {
        // see if we can find the method directly
        // most of the time this works and it's much faster
        try {
            Constructor ctor = clazz.getConstructor(parameterTypes);
            try {
                ctor.setAccessible(true);
            } catch (SecurityException se) {
            }
            return ctor;

        } catch (NoSuchMethodException e) { /* SWALLOW */
        }

        // search through all methods
        int paramSize = parameterTypes.length;
        Constructor[] ctors = clazz.getConstructors();
        for (int i = 0, size = ctors.length; i < size; i++) {
            // compare parameters
            Class[] ctorParams = ctors[i].getParameterTypes();
            int ctorParamSize = ctorParams.length;
            if (ctorParamSize == paramSize) {
                boolean match = true;
                for (int n = 0; n < ctorParamSize; n++) {
                    if (!MethodUtility.isAssignmentCompatible(
                            ctorParams[n], parameterTypes[n])) {
                        match = false;
                        break;
                    }
                }

                if (match) {
                    // get accessible version of method
                    Constructor ctor = getAccessibleConstructor(ctors[i]);
                    if (ctor != null) {
                        try {
                            ctor.setAccessible(true);
                        } catch (SecurityException se) {
                        }
                        return ctor;
                    }
                }
            }
        }

        return null;
    }
    /**
     * Returns a constructor with single argument.
     *
     * @param klass the class to be constructed
     * @return null if matching accessible constructor can not be found.
     * @see Class#getConstructor
     * @see #getAccessibleConstructor(java.lang.reflect.Constructor)
     */
    public static Constructor getAccessibleConstructor(Class klass,
            Class parameterType) {

        Class[] parameterTypes = { parameterType };
        return getAccessibleConstructor(klass, parameterTypes);

    }
    /**
     * Returns a constructor given a class and signature.
     *
     * @param klass          the class to be constructed
     * @param parameterTypes the parameter array
     * @return null if matching accessible constructor can not be found
     * @see Class#getConstructor
     * @see #getAccessibleConstructor(java.lang.reflect.Constructor)
     */
    public static Constructor getAccessibleConstructor(Class klass,
            Class[] parameterTypes) {

        try {
            return getAccessibleConstructor(klass
                    .getConstructor(parameterTypes));
        } catch (NoSuchMethodException e) {
            return (null);
        }

    }
    /**
     * Returns accessible version of the given constructor.
     *
     * @param ctor prototype constructor object.
     * @return <code>null</code> if accessible constructor can not be found.
     * @see java.lang.SecurityManager
     */
    public static Constructor getAccessibleConstructor(Constructor ctor) {

        // Make sure we have a method to check
        if (ctor == null) {
            return (null);
        }

        // If the requested method is not public we cannot call it
        if (!Modifier.isPublic(ctor.getModifiers())) {
            return (null);
        }

        // If the declaring class is public, we are done
        Class clazz = ctor.getDeclaringClass();
        if (Modifier.isPublic(clazz.getModifiers())) {
            return (ctor);
        }

        // what else can we do?
        return null;

    }
}

Related Tutorials