我的代码中有一个小问题
我有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? 我该如何解决?
感谢
答案 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的唯一区别是协方差返回类型......