2

I'm trying to invoke a method with an unknown number of parameter (when being invoked) using reflection.

I've seen a number of similar questions here, e.g. How to invoke method with variable arguments in java using reflection? or How to invoke a method in java using reflection but these use methods names: ReflectionExample.class.getMethod("test", int.class) which is not what I'm trying to do.

Please see the sample code below:

/* an arbitary class extending a base class */
public class MyClass extends MyBaseClass {

    private String message = "";

    public void setMessage(String value){
        this.message = value;
    }

    public String getMessage(){
        return this.message;
    }

    public String method1(){
        /* blah blah */
        return getMessage();
    }
 }

/* another class extending the arbitary class */
public class MyOtherClass extends MyClass {

    public List<T extends MyClass> method2(SomeEnum enumValue, Object otherValue){
        List<MyClass> list = new ArrayList<MyClass>();
        MyClass c = new MyClass();
        c.setMessage("first message: " + enumValue.toString());
        list.add(c);
        MyClass c = new MyClass();
        c.setMessage("second message: " + otherValue.toString());
        list.add(c);
        return list;
    }

    public Object method3(Object param1, Object param2, Object param3){
        /* ... */
    }
}

/* use reflection to determine how to process the result */
public class Resolver{

  public void DoReflect(MyBaseClass obj){

     Method[] methods = obj.getMethods();

     for (Method m : methods){
       /*
        * this invoke works fine for MyClass.method1
        * but throws an exception for MyOtherClass.method2 or MyOtherClass.method3
        */

       /* many thanks to Andy Turner for his assistance.
          I've edited the original post to show his recommended solution */
       Class<?>[] klasses = m.getParameterTypes(); 
       Object[] oobjects = new Object[klasses.length]; 
       for (int x =0; x<klasses.length; x++) 
           oobjects[x] = klasses[x].newInstance(); 
       Object value = m.invoke(myclass, oobjects)

       // ... do some stuff
     }
  }
}

I would very much appreciate any help you could give me on this.

Thanks in advance.

Community
  • 1
  • 1
Go Coding
  • 43
  • 1
  • 7
  • 1
    Have you looked at the [Javadoc for `Method`](https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html)? e.g. `getParameterTypes()` tells you how many parameters it expects (via its length), and the types they should have. – Andy Turner Feb 08 '16 at 14:32
  • What do you expect to happen when calling a method that requires 3 arguments with 0 arguments? – mhlz Feb 08 '16 at 14:34
  • 1
    Thank you both @Andy Turner and @mhlz. So are you saying something like`Class> klasses = m.getParameterTypes(); Object[] oobjects = new Object[klasses.length]; for (int x =0; x – Go Coding Feb 08 '16 at 15:55
  • @GoCoding looks basically right; try it. – Andy Turner Feb 08 '16 at 15:56
  • @AndyTurner great! much appreciated. I'll edit the original post in case someone else could use this. – Go Coding Feb 08 '16 at 15:59
  • I think possibly the more important question is why you want to use reflection- just messing around and trying to figure it out? If not, usually there are better ways to avoid it. – Straw1239 Feb 08 '16 at 17:16
  • @Straw1239 I'm using it in conjunction with a couple of custom annotations to help me build a series of dynamic sqls. You'll probably going to suggest Hibernate? I thought about it but it's like a sledge hammer and walnut ... However I'm open to suggestions ... – Go Coding Feb 08 '16 at 18:56

1 Answers1

-2
private static Object methodInvoke(Object instance, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
            return switch (method.getParameterCount()) {
                case 0 -> method.invoke(instance);
                case 1 -> method.invoke(instance, args[0]);
                case 2 -> method.invoke(instance, args[0], args[1]);
                case 3 -> method.invoke(instance, args[0], args[1], args[2]);
                default -> method.invoke(instance, args);
            };
}
ARNR
  • 43
  • 4