GetDeclaredMethods(java)中的问题

时间:2009-12-25 15:42:21

标签: java reflection inheritance

我的代码中有一个小问题

我有2个班级

public class A {

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

public class B extends A{

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

现在在我的代码中我想只打印在B类中声明的方法

以这种方式

B b = new B();

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

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

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

为什么输出

foo

foo

为什么GetDeclaredMethods还会在A类中找到foo? 我该如何解决?

感谢

6 个答案:

答案 0 :(得分:17)

您遇到问题的原因是两种方法的协变返回类型。因为你有一个协变返回类型(B的返回类型是B,而不是A,不像超类),引擎盖下的Java生成一个单独的方法,原始的返回类型充当1.5之前的字节码规范之间的桥梁。新的Java 1.5语言行为。

您应该用来检查的方法是isBridge()方法,因为它准确表达了您要排除的内容。所以最终的代码看起来像这样:

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

for (Method method : methods) {

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

答案 1 :(得分:2)

默认情况下,getDeclaredMethods()返回给定类的所有方法,以及它的父类和接口。但是,Method对象允许您通过调用Method上的getDeclaringClass()来测试Method所属的类。因此,当您遍历所有Method个对象时,可以添加逻辑以仅在方法属于B类时打印该方法。

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());
  }
}

编辑:上述代码无法正常工作 - 它返回B作为所有方法的声明类。 isSynthetic()方法似乎按预期工作,对于重写方法(来自A的方法)返回true,但对来自B的方法返回false。因此,以下代码可能就是您要找的内容。

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

答案 2 :(得分:1)

因为B.foo和A.foo是不同的方法。如果要覆盖方法A.foo,则方法B.foo必须返回A类。

答案 3 :(得分:0)

您可以调用m.getDeclaringClass()来查看它是来自A类还是B类的方法。

答案 4 :(得分:0)

这可能有效:

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
  }
}

答案 5 :(得分:0)

当你说if(!aMethods.contains(m))确实包含按名称比较时?参数类型?返回值类型?因为从想要的方法到not的唯一区别是协方差返回类型......