集册 Java实例教程 调用参数类型与对象类型完全匹配的方法。

调用参数类型与对象类型完全匹配的方法。

欢马劈雪     最近更新时间:2020-01-02 10:19:05

448
调用参数类型与对象类型完全匹配的方法。

/*******************************************************************************

 * Copyright (c) 2011 MadRobot.

 * All rights reserved. This program and the accompanying materials

 * are made available under the terms of the GNU Lesser Public License v2.1

 * which accompanies this distribution, and is available at

 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

 * 

 * Contributors:

 *  Elton Kent - initial API and implementation

 ******************************************************************************/
 /*
 时 代 J a v a 公 众 号 - N o w J a v  a . c o m 提供
 */

import java.lang.ref.Reference;

import java.lang.ref.SoftReference;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.lang.reflect.Modifier;

import java.security.AccessController;

import java.security.PrivilegedAction;

import java.util.Collections;

import java.util.Map;

import java.util.WeakHashMap;


public class Main{/* 来 自 n  o  w  j  a  v  a . c o m*/

    /**

     * <p>

     * Invoke a method whose parameter types match exactly the object types.

     * </p>

     * 

     * <p>

     * This uses reflection to invoke the method obtained from a call to

     * <code>getAccessibleMethod()</code>.

     * </p>

     * 

     * @param object

     *            invoke method on this object

     * @param methodName

     *            get method with this name

     * @param args

     *            use these arguments - treat null as empty array

     * @return The value returned by the invoked method

     * 

     * @throws NoSuchMethodException

     *             if there is no such accessible method

     * @throws InvocationTargetException

     *             wraps an exception thrown by the

     *             method invoked

     * @throws IllegalAccessException

     *             if the requested method is not accessible

     *             via reflection

     */

    public static Object invokeExactMethod(Object object,

            String methodName, Object... args)

            throws NoSuchMethodException, IllegalAccessException,

            InvocationTargetException {

        if (args == null) {

            args = ArrayUtils.EMPTY_OBJECT_ARRAY;

        }

        int arguments = args.length;

        Class<?>[] parameterTypes = new Class[arguments];

        for (int i = 0; i < arguments; i++) {

            parameterTypes[i] = args[i].getClass();

        }

        return invokeExactMethod(object, methodName, args, parameterTypes);

    }

    /**

     * <p>

     * Invoke a method whose parameter types match exactly the parameter types

     * given.

     * </p>

     * 

     * <p>

     * This uses reflection to invoke the method obtained from a call to

     * <code>getAccessibleMethod()</code>.

     * </p>

     * 

     * @param object

     *            invoke method on this object

     * @param methodName

     *            get method with this name

     * @param args

     *            use these arguments - treat null as empty array

     * @param parameterTypes

     *            match these parameters - treat null as empty array

     * @return The value returned by the invoked method

     * 

     * @throws NoSuchMethodException

     *             if there is no such accessible method

     * @throws InvocationTargetException

     *             wraps an exception thrown by the

     *             method invoked

     * @throws IllegalAccessException

     *             if the requested method is not accessible

     *             via reflection

     */

    public static Object invokeExactMethod(Object object,

            String methodName, Object[] args, Class<?>[] parameterTypes)

            throws NoSuchMethodException, IllegalAccessException,

            InvocationTargetException {

        if (args == null) {

            args = ArrayUtils.EMPTY_OBJECT_ARRAY;

        }

        if (parameterTypes == null) {

            parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;

        }

        Method method = getAccessibleMethod(object.getClass(), methodName,

                parameterTypes);

        if (method == null) {

            throw new NoSuchMethodException("No such accessible method: "

                    + methodName + "() on object: "

                    + object.getClass().getName());

        }

        return method.invoke(object, args);

    }

    /**

     * <p>

     * Return an accessible method (that is, one that can be invoked via

     * reflection) with given name and parameters. If no such method can be

     * found, return <code>null</code>. This is just a convenient wrapper for

     * {@link #getAccessibleMethod(Method method)}.

     * </p>

     * 

     * @param cls

     *            get method from this class

     * @param methodName

     *            get method with this name

     * @param parameterTypes

     *            with these parameters types

     * @return The accessible method

     */

    public static Method getAccessibleMethod(Class<?> cls,

            String methodName, Class<?>... parameterTypes) {

        try {

            return getAccessibleMethod(cls.getMethod(methodName,

                    parameterTypes));

        } catch (NoSuchMethodException e) {

            return (null);

        }

    }

    /**

     * <p>

     * Return an accessible method (that is, one that can be invoked via

     * reflection) that implements the specified Method. If no such method can

     * be found, return <code>null</code>.

     * </p>

     * 

     * @param method

     *            The method that we wish to call

     * @return The accessible method

     */

    public static Method getAccessibleMethod(Method method) {

        if (!MemberUtils.isAccessible(method)) {

            return null;

        }

        // If the declaring class is public, we are done

        Class<?> cls = method.getDeclaringClass();

        if (Modifier.isPublic(cls.getModifiers())) {

            return method;

        }

        String methodName = method.getName();

        Class<?>[] parameterTypes = method.getParameterTypes();


        // Check the implemented interfaces and subinterfaces

        method = getAccessibleMethodFromInterfaceNest(cls, methodName,

                parameterTypes);


        // Check the superclass chain

        if (method == null) {

            method = getAccessibleMethodFromSuperclass(cls, methodName,

                    parameterTypes);

        }

        return method;

    }

    /**

     * <p>

     * Return an accessible method (that is, one that can be invoked via

     * reflection) that implements the specified method, by scanning through all

     * implemented interfaces and subinterfaces. If no such method can be found,

     * return <code>null</code>.

     * </p>

     * 

     * <p>

     * There isn't any good reason why this method must be private. It is

     * because there doesn't seem any reason why other classes should call this

     * rather than the higher level methods.

     * </p>

     * 

     * @param cls

     *            Parent class for the interfaces to be checked

     * @param methodName

     *            Method name of the method we wish to call

     * @param parameterTypes

     *            The parameter type signatures

     * @return the accessible method or <code>null</code> if not found

     */

    private static Method getAccessibleMethodFromInterfaceNest(

            Class<?> cls, String methodName, Class<?>... parameterTypes) {

        Method method = null;


        // Search up the superclass chain

        for (; cls != null; cls = cls.getSuperclass()) {


            // Check the implemented interfaces of the parent class

            Class<?>[] interfaces = cls.getInterfaces();

            for (int i = 0; i < interfaces.length; i++) {

                // Is this interface public?

                if (!Modifier.isPublic(interfaces[i].getModifiers())) {

                    continue;

                }

                // Does the method exist on this interface?

                try {

                    method = interfaces[i].getDeclaredMethod(methodName,

                            parameterTypes);

                } catch (NoSuchMethodException e) {

                    /*

                     * Swallow, if no method is found after the loop then this

                     * method returns null.

                     */

                }

                if (method != null) {

                    break;

                }

                
展开阅读全文