Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 310
Dazel Avatar asked Dec 25 '09 15:12

Dazel


2 Answers

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());
   }   
}
like image 161
Yishai Avatar answered Oct 11 '22 14:10

Yishai


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]);
  }
}
like image 35
Kaleb Brasee Avatar answered Oct 11 '22 15:10

Kaleb Brasee