Java Reflection Method Get from Object getMethod(final Object object, final String methodName, final Object... arguments)

Here you can find the source of getMethod(final Object object, final String methodName, final Object... arguments)

Description

Returns object's method with the specified name and arguments.

License

Open Source License

Parameter

Parameter Description
object object
methodName method name
arguments method arguments

Exception

Parameter Description
NoSuchMethodException an exception
InvocationTargetException an exception
IllegalAccessException an exception

Return

object's method with the specified name and arguments

Declaration

public static Method getMethod(final Object object, final String methodName, final Object... arguments)
        throws NoSuchMethodException, InvocationTargetException, IllegalAccessException 

Method Source Code

//package com.java2s;
/*/*from  w  ww. ja  v  a  2 s  . c  om*/
 * This file is part of WebLookAndFeel library.
 *
 * WebLookAndFeel library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * WebLookAndFeel library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with WebLookAndFeel library.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.lang.reflect.*;

import java.util.*;

public class Main {
    /**
     * Methods lookup cache.
     */
    private static final Map<Class, Map<String, Method>> methodsLookupCache = new HashMap<Class, Map<String, Method>>();

    /**
     * Returns object's method with the specified name and arguments.
     * If method is not found in the object class all superclasses will be searched for that method.
     *
     * @param object     object
     * @param methodName method name
     * @param arguments  method arguments
     * @return object's method with the specified name and arguments
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public static Method getMethod(final Object object, final String methodName, final Object... arguments)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        return getMethod(object.getClass(), methodName, arguments);
    }

    /**
     * Returns object's method with the specified name and arguments.
     * If method is not found in the object class all superclasses will be searched for that method.
     *
     * @param aClass     object class
     * @param methodName method name
     * @param arguments  method arguments
     * @return object's method with the specified name and arguments
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public static Method getMethod(final Class aClass, final String methodName, final Object... arguments)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // todo Methods priority check (by super types)
        // todo For now some method with [Object] arg might be used instead of method with [String]
        // todo To avoid issues don't call methods with same amount of arguments and which are castable to each other

        // Method key
        final Class[] classTypes = getClassTypes(arguments);
        final String key = aClass.getCanonicalName() + "." + methodName + argumentTypesToString(classTypes);

        // Checking cache
        Method method = null;
        Map<String, Method> classMethodsCache = methodsLookupCache.get(aClass);
        if (classMethodsCache != null) {
            method = classMethodsCache.get(key);
        } else {
            classMethodsCache = new HashMap<String, Method>(1);
            methodsLookupCache.put(aClass, classMethodsCache);
        }

        // Updating cache
        if (method == null) {
            method = getMethodImpl(aClass, methodName, arguments);
            classMethodsCache.put(key, method);
        }

        return method;
    }

    /**
     * Returns object's method with the specified name and arguments.
     * If method is not found in the object class all superclasses will be searched for that method.
     *
     * @param topClass     initial object class
     * @param currentClass object class we are looking in for the method
     * @param methodName   method name
     * @param types        method argument types
     * @return object's method with the specified name and arguments
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     */
    private static Method getMethod(final Class topClass, final Class currentClass, final String methodName,
            final Class[] types) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        // Searching for the specified method in object's class or one of its superclasses
        for (final Method method : currentClass.getDeclaredMethods()) {
            // Checking method name
            if (method.getName().equals(methodName)) {
                // Checking method arguments count
                final Class<?>[] mt = method.getParameterTypes();
                if (mt.length == types.length) {
                    // Checking that arguments fit
                    boolean fits = true;
                    for (int i = 0; i < mt.length; i++) {
                        if (!isAssignable(mt[i], types[i])) {
                            fits = false;
                            break;
                        }
                    }
                    if (fits) {
                        // Returning found method
                        return method;
                    }
                }
            }
        }

        // Search object superclass for this method
        final Class superclass = currentClass.getSuperclass();
        if (superclass != null) {
            return getMethod(topClass, superclass, methodName, types);
        }

        // Throwing proper method not found exception
        throw new NoSuchMethodException(
                topClass.getCanonicalName() + "." + methodName + argumentTypesToString(types));
    }

    /**
     * Returns class for the specified canonical name.
     *
     * @param canonicalName class canonical name
     * @return class for the specified canonical name
     * @throws ClassNotFoundException
     */
    public static <T> Class<T> getClass(final String canonicalName) throws ClassNotFoundException {
        return (Class<T>) Class.forName(canonicalName);
    }

    /**
     * Returns an array of argument class types.
     *
     * @param arguments arguments to process
     * @return an array of argument class types
     */
    public static Class[] getClassTypes(final Object[] arguments) {
        final Class[] parameterTypes = new Class[arguments.length];
        for (int i = 0; i < arguments.length; i++) {
            parameterTypes[i] = arguments[i] != null ? arguments[i].getClass() : null;
        }
        return parameterTypes;
    }

    /**
     * Returns text representation for array of argument types.
     *
     * @param argTypes argument types
     * @return text representation for array of argument types
     */
    private static String argumentTypesToString(final Class[] argTypes) {
        final StringBuilder buf = new StringBuilder("(");
        if (argTypes != null) {
            for (int i = 0; i < argTypes.length; i++) {
                if (i > 0) {
                    buf.append(", ");
                }
                final Class c = argTypes[i];
                buf.append((c == null) ? "null" : c.getCanonicalName());
            }
        }
        return buf.append(")").toString();
    }

    /**
     * Returns object's method with the specified name and arguments.
     * If method is not found in the object class all superclasses will be searched for that method.
     *
     * @param aClass     object class
     * @param methodName method name
     * @param arguments  method arguments
     * @return object's method with the specified name and arguments
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    protected static Method getMethodImpl(final Class aClass, final String methodName, final Object[] arguments)
            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        // This enhancement was a bad idea and was disabled
        // In case method is protected/private or located in one of superclasses it won't be found
        //        if ( arguments.length == 0 )
        //        {
        //            // Searching simple method w/o arguments
        //            method = aClass.getMethod ( methodName );
        //            method.setAccessible ( true );
        //        }

        // Searching for more complex method
        final Class[] types = getClassTypes(arguments);
        final Method method = getMethod(aClass, aClass, methodName, types);
        method.setAccessible(true);
        return method;
    }

    /**
     * Returns whether first type is assignable from second one or not.
     *
     * @param type checked whether is assignable, always not null
     * @param from checked type, might be null
     * @return true if first type is assignable from second one, false otherwise
     */
    public static boolean isAssignable(final Class type, final Class from) {
        if (from == null) {
            return !type.isPrimitive();
        } else if (type.isAssignableFrom(from)) {
            return true;
        } else if (type.isPrimitive()) {
            if (type == boolean.class) {
                return Boolean.class.isAssignableFrom(from);
            } else if (type == int.class) {
                return Integer.class.isAssignableFrom(from);
            } else if (type == char.class) {
                return Character.class.isAssignableFrom(from);
            } else if (type == byte.class) {
                return Byte.class.isAssignableFrom(from);
            } else if (type == short.class) {
                return Short.class.isAssignableFrom(from);
            } else if (type == long.class) {
                return Long.class.isAssignableFrom(from);
            } else if (type == float.class) {
                return Float.class.isAssignableFrom(from);
            } else if (type == double.class) {
                return Double.class.isAssignableFrom(from);
            } else if (type == void.class) {
                return Void.class.isAssignableFrom(from);
            }
        }
        return false;
    }
}

Related

  1. getMethod(Class klass, String methodName, Object... params)
  2. getMethod(Class objectType, String methodName, Class... parameterTypes)
  3. getMethod(Class type, String name, Object[] args)
  4. getMethod(final Class clazz, final String methodName, final Class[] parTypes, final Object[] parameters)
  5. getMethod(final Object object, final String methodName, final Class... parameterClass)
  6. getMethod(final Object object, final String methodName, final Object... arguments)
  7. getMethod(final Object object, String methodName, final Class[] argTypes)
  8. getMethod(final Object target, final String methodName, final Class... argumentTypes)
  9. getMethod(final String methodName, final Object obj, final Class... argTypes)