views:

150

answers:

4

A while ago I had a similar question when using Class.getMethod and autoboxing, and it made sense to implement this in your own lookup algorithm. But what really confused me a little was that the following is not working either:

public class TestClass
{
    public String doSomething(Serializable s)
    {
        return s.toString();
    }

    public static void main(String[] args) throws SecurityException, NoSuchMethodException
    {
        TestClass tc = new TestClass();
        Method m = tc.getClass().getMethod("doSomething", String.class);
    }
}

String.class implements the Serializable interface and I really expected it to be included in the lookup method. Do I have to consider this in my own lookup algorithms as well?

EDIT: I did read the Javadoc, so let me emphasise the second part of the question: And if so do you have suggestions on how to do that fast (I already had to add some custom matching and converting algorithms and I don't want it to get too slow)?

+1  A: 

getMethod isn't meant to find methods which are compatible with the given parameter types - it's meant to find methods with exactly the given parameter types.

You'd need to call getMethods() to find all the methods, then filter by name and number of parameters, then work out which of those are actually applicable.

Jon Skeet
A: 

Why would you call getMethod with String.class? Method signatures are exactly mapped. It doesn't make any sense to look up a method by the same criteria as if you will call them.

fastcodejava
+4  A: 

The javadoc for Class.getMethod is very explicit:

The parameterTypes parameter is an array of Class objects that identify the method's formal parameter types, in declared order.

It offers no scope for subtypes.

skaffman
+1  A: 

As per your edit, you can make use of Class#isAssignableFrom(). Here's a basic kickoff example (leaving obvious (runtime) exception handling aside):

package com.stackoverflow.q2169497;

import java.io.Serializable;
import java.lang.reflect.Method;

public class Test {

    public String doSomething(Serializable serializable) {
        return serializable.toString();
    }

    public static void main(String[] args) throws Exception {
        Test test = new Test();
        for (Method method : test.getClass().getMethods()) {
            if ("doSomething".equals(method.getName())) {
                if (method.getParameterTypes()[0].isAssignableFrom(String.class)) {
                    System.out.println(method.invoke(test, "foo"));
                }
            }
        }
    }

}

This should print foo to stdout.

BalusC