0

I want to use a method from a 3rd party package I use. This is the signature:

java.lang.String buildMenuPath(java.lang.Object... objects);

The method can be used as follows (to name a few):

  1. buildMenuPath(1,1,1) //3 ints
  2. buildMenuPath("str",1,1) // 1 string 2 ints
  3. buildMenuPath("str",1) // 1 string 1 int

Through reflection, I try to get this method and follow usage #2 and #3.

Attempt #1, getting the exact signature I will use (String.class, Integer.class)

ArrayList pathArr = new ArrayList();
pathArr.add("Window");
pathArr.add(i);
Method method  = myObj.getClass().getMethod("buildMenuPath",String.class, Integer.class);
method.invoke(myObj,pathArr.toArray())
  • Throws: java.lang.NoSuchMethodException

Attempt #2, getting the arbitrary arguments method:

ArrayList pathArr = new ArrayList();
pathArr.add("Window");
pathArr.add(i);
Method method  = myObj.getClass().getMethod("buildMenuPath",Object[].class);
method.invoke(myObj,pathArr.toArray())
  • Looks like it gets the method but throws: java.lang.IllegalArgumentException

But if I call manually, with myObj.buildMenuPath("Window",6); it works.

How can I solve this problem through reflection?

Adelin
  • 7,809
  • 5
  • 37
  • 65
  • Varargs is syntactic sugar done by the compiler. As far as the JVM, and hence reflection, is concerned, the signature of the method is `buildMenuPath(Object[] objects)`, so that's the method you should look for. – Andreas Apr 17 '18 at 06:17
  • Try `method.invoke(myObj, new Object[] {new Object[] {"Window", i}})` in Attempt #2. And see [How to work with varargs and reflection](https://stackoverflow.com/questions/2600854/how-to-work-with-varargs-and-reflection). –  Apr 17 '18 at 06:40
  • @saka1029 thanks - the problem is I construct `pathArr` dynamically, so I won't *(easily)* know at the time I call `.invoke` how many args I want to call with – Adelin Apr 17 '18 at 06:58

1 Answers1

1

You need to know the exact signature of the function (look through documentation), it may take a variable list of arguments of Object type for example, or it may be overloaded, but the argument types may not be String and int.

Finally, when calling Invoke(), cast the array of arguments to (Object)

In your case, should be:

ArrayList pathArr = new ArrayList();
pathArr.add("Window");
pathArr.add(i);
Method method  = myObj.getClass().getMethod("buildMenuPath",Object[].class);
method.invoke(myObj,(Object)pathArr.toArray())
Adelin
  • 7,809
  • 5
  • 37
  • 65
oviuan
  • 108
  • 5
  • Did you even read the question? What do you think the following is? *This is the signature: `java.lang.String buildMenuPath(java.lang.Object... objects);`* – Andreas Apr 17 '18 at 06:19
  • 1
    sorry, I missed that. You should cast your array to (Object) when calling Invoke() – oviuan Apr 17 '18 at 06:28
  • @oviuan thank you. casting solved the problem, just as the answer in the duplicate link said. If you edit your answer to clarify that I'll upvote & accept it. thanks – Adelin Apr 17 '18 at 07:00
  • Thanks @Adelin, added the edit. Sorry again about missing the signature line :) – oviuan Apr 17 '18 at 08:40