Michael
Michael

Reputation: 233

reflection finding method on class using superclass as parameter

small question about something I can't get my head around. I have the following:

public abstract class A 
{
  ...
}

and an extension of this class

public class B extends A
{
 ...
}

Now I have a class that looks like the following

public class DoStuff extends AbstractDoStuff
{
  public void doNiceStuff(B b)
  {
    ...
  }
}

It is this class' method I'm trying to invoke by reflection. However I'm trying to invoke this method from a package that is not aware of B and only knows about A. This is due to dependencies of the projects

So I have the following code that needs to find method doNiceStuff(B):

public abstract class AbstractDoStuff
{
  public static Method getGetterMethod(Class<? extends AbstractDoStuff> stuffClass) throws NoSuchMethodException
  {
    Method method = stuffClass.getDeclaredMethod("doNiceStuff", A.class)
    ...
  }
}

so the getDeclaredMethod should find doNiceStuff on class DoStuff but it seems that reflection isn't able to find the method using the superclass A.class. However I can't provide B.class there as the package doesn't know anything about the existence of B.

any idea if there is a way to fix this?

regards

Michael

Upvotes: 2

Views: 2726

Answers (1)

ppeterka
ppeterka

Reputation: 20726

You could use a bit more reflection to get it:

Method[] methods = stuffClass.getMethods(); 
for(Method m: methods) {
   if(m.getName().equals("doNiceStuff")) {
      Class<?> paramTypes = m.getParameterTypes();

      //condition on the desired parameter types comes here
      if(paramTypes.length==1 && A.class.isAssignableFrom(paramTypes[0]) {
        //we found it!
      }

   }
}

Why is isSuperClass() not good in this case?

Suppose we'd do it like this:

if (paramTypes.length == 1 && paramTypes[0].getSuperclass().equals(A.class)) {
...

This solution would be good for the class B, but what if we have a class C?

public class C extends B {


    public void doNiceStuff(C arg0) {
        //do nice stuff here
    }

}

This condition

paramTypes[0].getSuperclass().equals(A.class)

would be false! paramTypes[0].getSuperClass() is B.class, and is not equal to A.class...

Class.getMethods()

Returns an array containing Method objects reflecting all the public member methods of the class or interface represented by this Class object, including those declared by the class or interface and those inherited from superclasses and superinterfaces.

Class.isAssignableFrom()

Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter. It returns true if so; otherwise it returns false. If this Class object represents a primitive type, this method returns true if the specified Class parameter is exactly this Class object; otherwise it returns false. Specifically, this method tests whether the type represented by the specified Class parameter can be converted to the type represented by this Class object via an identity conversion or via a widening reference conversion. See The Java Language Specification, sections 5.1.1 and 5.1.4 , for details.

Recommended reading:

Upvotes: 2

Related Questions