Using java.lang.reflect.getMethod with polymorphic methods

前端 未结 3 2111
既然无缘
既然无缘 2020-12-19 05:15

Consider the following snippet:

public class ReflectionTest {

    public static void main(String[] args) {

        ReflectionTest test = new ReflectionTest         


        
相关标签:
3条回答
  • 2020-12-19 05:45

    The reflection tutorial

    suggest the use of Class.isAssignableFrom() sample for finding print(String)

        Method[] allMethods = c.getDeclaredMethods();
        for (Method m : allMethods) {
            String mname = m.getName();
            if (!mname.startsWith("print") {
                continue;
            }
            Type[] pType = m.getGenericParameterTypes();
            if ((pType.length != 1)
                || !String.class.isAssignableFrom(pType[0].getClass())) {
                continue;
            }
         }
    
    0 讨论(0)
  • 2020-12-19 05:59

    FYI, it is how I invoke method using reflection with multiple parameters without giving their types.

    public class MyMethodUtils {
        /**
         * Need to pass parameter classes
         */
        public static Object invoke(Object invoker, String methodName, Object[] parameters, Class[] parameterClasses) throws Exception {
            Method method = invoker.getClass().getMethod(methodName, parameterClasses);
            Object returnValue = method.invoke(invoker, parameters);
            return returnValue;
        }
    
        /**
         * No need to pass parameter classes
         */
        public static Object invoke(Object invoker, String methodName, Object[] parameters) throws Exception {
            Method[] allMethods = invoker.getClass().getDeclaredMethods();
            Object returnValue = null;
            boolean isFound = false;
            for (Method m : allMethods) {
                String mname = m.getName();
                if (!mname.equals(methodName)) {
                    continue;
                }
                Class[] methodParaClasses = m.getParameterTypes();
                for (int i = 0; i < methodParaClasses.length; i++) {
                    Class<?> parameterClass = parameters[i].getClass();
                    Class<?> methodParaClass = methodParaClasses[i];
                    boolean isAssignable = methodParaClass.isAssignableFrom(parameterClass);
                    if (!isAssignable) {
                        continue;
                    }
                }
                returnValue = m.invoke(invoker, parameters);
                isFound = true;
            }
            if (!isFound) {
                throw new RuntimeException("Cannot find such method");
            }
    
            return returnValue;
        }
    
    }
    

    Sample Usage:

        MyMethodUtils.invoke(student, "setNameAndMarks", new Object[] { "John", marks }, new Class[] { String.class, Collection.class });
        MyMethodUtils.invoke(student, "setNameAndMarks", new Object[] { "John", marks });
    

    However, for the method invoke(Object invoker, String methodName, Object[] parameters), it is possible to invoke wrong method if the signature is ambiguous. For example, if there is two methods for the invoker:

    public void setNameAndMarks(String name, Collection<Integer> marks);
    public void setNameAndMarks(String name, ArrayList<Integer> marks);
    

    Passing the following parameter may invoke wrong method

    setNameAndMarks("John", new ArrayList<Integer>());
    
    0 讨论(0)
  • 2020-12-19 06:04

    The easy way to do this is via java.beans.Statement or java.beans.Expression. Does all these hard yards for you.

    getMethod() is obviously unaware that a String could be fed to a method that expects an Object

    'Unaware' is a strange way to put it. getMethod() adheres to its specification. You have to supply the formal parameters, not the types of the actual arguments.

    0 讨论(0)
提交回复
热议问题