0

I'm doing some weird reflection stuff to get around wrapping a whole bunch of methods in a class. The java docs suggest that null would be the solution, but it fails with NoSuchMethodException.

 public Method getMethod(String name, Class[] parameterTypes) throws NoSuchMethodException, SecurityException 

If parameterTypes is null, it is treated as if it were an empty array.

To begin with I'm trying:

private <T> T invokeWrappedFunction(Object instance, String methodName, Object... args) { try{ Method m = instance.getClass().getMethod(methodName, (args == null ? null : args.getClass())); return (T) m.invoke(instance, args); } catch(Exception e) { //This is an example, you're lucky I even acknowledged the exception! } } 

Now eventually there will be lots of extra functionality in there and instance isn't an unknown type so I can do helpful stuff on failures and such. The real question is how do I get the getMethod working?

6
  • Looking at this more closely, I might also have an issue with args.getClass() so maybe my cleverness is hubris :( Commented Jan 5, 2012 at 1:02
  • You do have a problem with args.getClass(). It will return the class of an object array which is an instance of Class, not Class[]. You need to construct a new Class array and fill it with each arg.getClass(). Even then, though, I'm not sure that will work with any polymorphism/subclassing because getClass() may not correspond to the formal parameter list. Commented Jan 5, 2012 at 1:15
  • If the method takes a bunch of arguments of different types, I think you are out of luck. If it takes an array of the same type, you can verify that args really is an array, then do Class.getComponentType(); See updated answer below. Commented Jan 5, 2012 at 1:23
  • I think type erasure may pose an issue, though--what are some signatures you're trying to call? (The null works just fine, btw.) Commented Jan 5, 2012 at 1:38
  • See this. But some additional info on what the generic classes look like might help. Commented Jan 5, 2012 at 1:45

2 Answers 2

1

Based on the comments I'm adding an answer to illustrate what I mean.

private <T> T invokeWrappedFunction(Object instance, String methodName, Object... args) { Class[] classes = null; if (args != null) { classes = new Class[args.length]; for (int i = 0; i < args.length; ++i) { classes[i] = args[i].getClass(); } } try { Method m = instance.getClass().getMethod(methodName, classes); return (T) m.invoke(instance, args); } catch(Exception e) { //This is an example, you're lucky I even acknowledged the exception! } } 

This still will not work in some cases, though. If the object you're passing in is a subclass of the formal parameter type it will not work.

For example:

interface I { void method(); } class C implements I { public void method() { ... code ... } } 

If you try to reflect a method expecting to take an I but you pass it a C then getMethod(...) will throw an exception instead of returning the method you want because C is not equal to I.

Sign up to request clarification or add additional context in comments.

2 Comments

Ouch, many of the arguments happen to be interfaces so I'm pretty well stuck. Thanks for your time though!
Just for the record: you can re-create Java's way of picking the correct method (testing isAssignableFrom() or some other way). I'm not exactly sure how the JVM picks the method, but I'm sure it's documented somewhere. You'd need to use getMethods() and find the most appropriate match, but it wouldn't be pretty.
1

I think you pass a new Class[0];

e.g.

final static Class[] NO_ARGS = new Class[0]; Method m = Method m = instance.getClass().getMethod(methodName, NO_ARGS); 

ADDED

Maybe I'm not understanding the complete question. If the problem is not the no-args version. but the with args version, you can handle it if the args are an array of all the same type. If they are different types I think you are in trouble.

First, verify that args is not null and that it is an array, then call Class.getComponentType(), e.g.

if (args != null) { Class c = args.getClass(); if (c.isArray()) Class arrayClass = c.getComponentType(); // do something here... } 

2 Comments

You might be able to use @mange suggestion, plus some sort of a Map that maps your concrete classes to the magical interface you need to get the right method. Of course, if they implement more than 1 interface (as is likely) it could quickly get very messy. I guess you could loop through all their interfaces till you don't get an Exception, but that seems a bit much.
Thanks, in the end I'll just maintain the twenty or so very similar functions in the wrapper. This stuff was just getting so hard to comprehend that it won't actually be easier to maintain.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.