Dazel
Dazel

Reputation: 81

Problem in the GetDeclaredMethods (java)

I have a small problem in my code

I have 2 classes

public class A {

     public A foo(int a) {return new A();}
}

public class B extends A{

     public B foo(int x){ return new B();}
}

now in my code I want to print only the method that was declared in class B

in this way

B b = new B();

Method[] m = b.getClass().getDeclaredMethods();

for (int i = 0; i < m.length; i++) {

System.out.print(m[i].getName());   
}

why the output is

foo

foo

why the GetDeclaredMethods finds also the foo in the A class? how can i fix it?

thanks

Upvotes: 8

Views: 7653

Answers (6)

T_lord
T_lord

Reputation: 1

When you says if( ! aMethods.contains(m) ) does contains compare by name? arguments type? return value type? because the only difference from the wanted method to the not is the covariance return type...

Upvotes: 0

Yishai
Yishai

Reputation: 91871

The reason you are having a problem is because of the covariant return types of your two methods. Because you have a covariant return type (the return type of B is B, not A, unlike the superclass), Java under the hood generates a separate method with the original return type to act as a bridge between the pre-1.5 bytecode specification the new Java 1.5 language behavior.

The method you should be using to check, though is the isBridge() method, as it expresses exactly what you intend to exclude. So the final code would look something like this:

Method[] methods = B.class.getDeclaredMethods();

for (Method method : methods) {

   if (!method.isBridge()) {
       System.out.println(method.getName());
   }   
}

Upvotes: 18

Kaleb Brasee
Kaleb Brasee

Reputation: 51935

By default, getDeclaredMethods() returns all of the methods for the given class, as well as it's parent classes and interfaces. However, the Method object allows you to test which class a Method belongs to by calling getDeclaringClass() on that Method. So when you cycle through all the Method objects, you can add logic to only print a method if it belongs to the B class.

Method[] m = b.getClass().getDeclaredMethods();
for (int i = 0; i < m.length; i++) {
  if (m[i].getDeclaringClass().equals(B.class)) {
    System.out.print(m[i].getName());
  }
}

EDIT: The above code doesn't work as desired -- it returns B as the declaring class of all methods. The isSynthetic() method appears to work as desired, returning true for an overridden method (one that came from A), but false for one that came from B. So the following code might be what you're looking for.

Method[] m = b.getClass().getDeclaredMethods();
for (int i = 0; i < m.length; i++) {
  if (!m[i].isSynthetic()) {
    System.out.print(m[i]);
  }
}

Upvotes: 2

Tom Neyland
Tom Neyland

Reputation: 6968

This may work:

A a = new A();
B b = new B();

List<Method> aMethods = Arrays.asList(a.getClass().getMethods());
List<Method> bMethods = Arrays.asList(b.getClass().getMethods());

for ( Method m : bMethods )
{
  if( ! aMethods.contains(m) )
  {
  //Your action code here
  }
}

Upvotes: 0

Denis Palnitsky
Denis Palnitsky

Reputation: 18387

Because B.foo and A.foo is different methods. If you want to override method A.foo, then method B.foo must return class A.

Upvotes: 1

Jim Ferrans
Jim Ferrans

Reputation: 31012

You can call m.getDeclaringClass() to see if it's the Method from Class A or Class B.

Upvotes: 0

Related Questions