views:

84

answers:

2

Suppose I have an interface:

public interface FooInterface {
     public void someMethod();
    }

and I have a class that implements this interface:

public class FooClass implements FooInterface {
     public void someMethod() {
      //do cool things
     }
     public void someOtherMethod() {
      //do other cool things
     }
    }

Is there an easy way to find, reflectively, the method on FooClass that maps up to the someMethod on the FooInterface?

I have something similar to the following doing this calculation, but I was curious if anyone knew of a built in system in Java to do this calculation? I have worked out the following code to do it (there may be bugs, so beware):

public boolean isMethodEquality(Method meth1, Method meth2) {

  //Check declaring classes for equality
  boolean isAssignable;
  isAssignable = meth1.getDeclaringClass().isAssignableFrom(
    meth2.getDeclaringClass();
  isAssignable |= meth2.getDeclaringClass().isAssignableFrom(
    meth1.getDeclaringClass());
  if (!isAssignable) {
      return false;
  }
  //check the names for equality
  if (!meth1.getName().equals(meth2.getName())) {
    return false;
  }
  //check the parameters for equality
  if (meth1.getParameterTypes().length != meth2.getParameterTypes().length) {
    return false;
  }
  for (int i = 0; i < meth1.getParameterTypes().length; i++) {
    if (!meth1.getParameterTypes()[i].equals(meth2.getParameterTypes()[i])) {
      return false;
    }
  }
  return true;
}

The above should check the signatures. Is there another, built-in way to do this?

I attmepted .equals, but that did not work, which makes sense. The methods are different implementation patterns of the same method (where, in this case, one is simply a declaration with no definition and another is the definition).

I also realize I could simply add an inheritable annotation, but I would prefer to avoid this as it can led to class explosion.

As noted by one of the commenters, Annotations only inherit on classes. See the java docs for more details.

What I am really looking for is an "isAssignableFrom" for methods, or a way to compare method signatures easily.

Thanks.

A: 

Method implements equals, so you should be able to just call that. The definition is a little different from what you are doing though. If you need it specifically to follow the logic you are writing, then you will have to roll your own, AFAIK.

Yishai
Yeah, the equals does not check signatures, just that the method is from the same class, is the same method, and was loaded by the same class loader. I really want to know if it is an implementation of another method - i.e. is an override.
aperkins
+3  A: 

The easiest (and no, it's not going to perform well but presumably that's not something you'd care about in this case) way to do this is to call concreteClass.getMethod():

Method interfaceMethod = ...; // method whose implementation you're looking for
try {
    Method implementationMethod = concreteClass.getMethod(
        interfaceMethod.getName(), interfaceMethod.getParameterTypes());
} catch (NoSuchMethodException E) {
    // your class may be abstract and thus would not implement given method
} catch (SecurityException E) {
    // insufficient permissions
}
ChssPly76
Thank you - this will work very well. And for performance, you could cache the call if necessary, thereby only incurring the lookup hit once. I can't believe I forgot this :)
aperkins