59

On my current project, I've felt the need to create a sort of simulated callback system in Java using reflection. However, I'm having issues getting my reflection to actually function. The code at fault follows:

public Callback(Object parentObj, String methodName, Class<?>...parameters)
{
    if(parentObj == null)
        throw new IllegalArgumentException("parentObj cannot be null", new NullPointerException());

    Class<?> clazz = parentObj.getClass();

    // Trace debugging, see output
    for(Method m : clazz.getDeclaredMethods())
        if(m.getName().equals("myMethod")) System.out.println (m);

    try { this.method = clazz.getMethod(methodName, parameters); }
    catch(NoSuchMethodException nsme) { nsme.printStackTrace(); } // Exception caught
    catch(SecurityException se) { se.printStackTrace(); }

    this.parentObj = parentObj;
    this.parameters = parameters;
}

When I construct the Callback object, I'm using syntax like this:

new Callback(this, "myMethod", boolean.class)

When I try to create my pseudo-callback, it hits the NoSuchMethodException catch block. I've included some trace debugging above to show the output of one of my methods failing. The output:

private void my.package.MyClass.myMethod(boolean)
java.lang.NoSuchMethodException: my.package.MyClass.myMethod(boolean)
    at java.lang.Class.getMethod(Class.java:1605)
    at my.package.other.Callback.<init>(Callback.java:63)

I couldn't figure the problem out, so I started hunting, to little avail. The best I could find was mention of versioning conflict between the compiled JAR and the runtime. However, MyJar.jar/META-INF/MANIFEST.MF contains Created-By: 1.6.0_02 (Sun Microsystems Inc.). My IDE is running C:\Program Files\Java\jdk1.6.0_02\bin\javac.exe to compile my project. I'm using C:\Program Files\Java\jdk1.6.0_02\bin\java.exe to run my JAR.

I'm at a loss why Class.getMethod is claiming the method doesn't exist, but Class.getMethods seems to have no problem finding it. Help? :(

3
  • 1
    That's why you don't rely on Reflection, which is unreliable at best. Commented Jul 8, 2010 at 2:27
  • I wouldn't say it's unreliable, but it can be complicated and inefficient. Commented Jul 8, 2010 at 2:30
  • 1
    It's certainly less reliable than something your compiler can prove is correct. :-) Commented Jul 8, 2010 at 2:37

4 Answers 4

127

Your method is private but getMethod() only returns public method.

You need to use getDeclaredMethod().

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

5 Comments

Yes! This fixes the problem without forcing me to use public methods. Thanks!
3 years later... That makes a lot of sense in my case. Although I started reading the documentation for both methods at docs.oracle.com/javase/1.5.0/docs/api/java/lang/…, java.lang.Class...) and they don't mention such information. Maybe you looked into the code? Good for you. +1
Was banging my head on the wall for 2 hours straight. Thanks man !
Awesome naming conventions java... how about getPrivateMethod .. lordy
This helped me but in reverse. I had a public method I was trying to call with getDeclaredMethod(), and it didn't find it. Swapped over to getMethod() and it works
8

You need the parameter list to be absolutely correct for the method you want for the call to succeed.

I've found that tiny steps are important when doing reflection because the compiler doesn't help. Write a small snippet which actually invokes exactly the method you want to in this particular case, and then when that works, generalize it into the framework here. I would focus on the parameters passed.

1 Comment

This was the issue in my case. I wasn't providing types of parameter for the method I wanted to get. My code before looked like Method method = SearchApiController.class.getMethod("searchPost") but my method was taking bunch of parameters which I missed specified while getting it via reflection. My code after worked like a charm. Method method = SearchApiController.class.getMethod("searchPost", String.class, SearchQuery.class, String.class, String.class, String.class);
5

The Javadoc for getMethod isn't explicit, but it looks like it might throw a NoSuchMethodException for methods that aren't public, and your method is private.

1 Comment

Yup, that's it. Your suggestion had me pour through the source code for Class. getMethod calls (private) getMethod0. getMethod0 calls privateGetDeclaredMethods(true), where true is "publicOnly"
0

The versioning issue that can cause NoSuchMethodException isn't a difference between the compiler versions. It's a difference in the version of (in your case) MyClass at compile time versus runtime.

Since you're using reflection you issue might have nothing to do with versioning, though. Certainly that would not explain different behavior between getMethod and getDeclaredMethods, because you're running them against the same Class instance, hence a version difference isn't really possible.

Are you sure that the parameters match your actual method?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.