GetDeclaredMethods(java)中的问题

我的代码中有一个小问题

我有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? 我该怎么办呢?

谢谢

您遇到问题的原因是因为您的两种方法的协变返回类型。 因为你有一个协变返回类型(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()); } } 

默认情况下, 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]); } } 

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

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

这可能有效:

 A a = new A(); B b = new B(); List aMethods = Arrays.asList(a.getClass().getMethods()); List bMethods = Arrays.asList(b.getClass().getMethods()); for ( Method m : bMethods ) { if( ! aMethods.contains(m) ) { //Your action code here } } 

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