简体   繁体   English

GetDeclaredMethods(java)中的问题

[英]Problem in the GetDeclaredMethods (java)

I have a small problem in my code 我的代码有一个小问题

I have 2 classes 我有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();}
}

now in my code I want to print only the method that was declared in class B 现在在我的代码中,我只想打印在类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? 为什么GetDeclaredMethods在A类中也找到foo? how can i fix it? 我该如何解决?

thanks 谢谢

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. 因为您有一个协变返回类型(B的返回类型是B,而不是A,与超类不同),所以Java幕后将使用原始返回类型生成一个单独的方法,以充当1.5之前的字节码规范与新的Java 1.5语言行为。

The method you should be using to check, though is the isBridge() method, as it expresses exactly what you intend to exclude. 尽管isBridge()方法是您要检查的方法,但它恰好表示您要排除的内容。 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());
   }   
}

By default, getDeclaredMethods() returns all of the methods for the given class, as well as it's parent classes and interfaces. 默认情况下, getDeclaredMethods()返回给定类的所有方法,以及它的父类和接口。 However, the Method object allows you to test which class a Method belongs to by calling getDeclaringClass() on that Method . 但是,通过Method对象,可以通过在Method上调用getDeclaringClass()来测试该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对象时,可以添加逻辑以仅打印属于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());
  }
}

EDIT: The above code doesn't work as desired -- it returns B as the declaring class of all methods. 编辑:上面的代码无法按需工作-它返回B作为所有方法的声明类。 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 . isSynthetic()方法似乎可以按预期工作,对于被覆盖的方法(来自A方法)返回true,但是对于来自B方法返回false。 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]);
  }
}

Because B.foo and A.foo is different methods. 因为B.foo和A.foo是不同的方法。 If you want to override method A.foo, then method B.foo must return class A. 如果要覆盖方法A.foo,则方法B.foo必须返回类A。

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

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

When you says if( ! aMethods.contains(m) ) does contains compare by name? 当您说if(!aMethods.contains(m))是否包含按名称进行比较时? arguments type? 参数类型? return value type? 返回值类型? because the only difference from the wanted method to the not is the covariance return type... 因为从通缉方法到不是唯一的区别是协方差返回类型...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM