通过反射获取给定类的可访问方法列表

2022-09-01 05:19:42

有没有办法获取给定类可访问(不一定是公共)的方法列表?有问题的代码将处于完全不同的类中。

例:

public class A {
  public void methodA1();
  protected void methodA2();
  void methodA3();
  private void methodA4();
}

public class B extends A {
  public void methodB1();
  protected void methodB2();
  private void methodB3();
}

对于我想获得的课程:B

  • 所有自己的方法
  • methodA1和从类methodA2A
  • methodA3当且仅当类与BA

methodA4永远不要包含在结果中,因为 class 无法访问它。为了再次澄清,需要查找和返回上述方法的代码将位于完全不同的类/包中。B

现在,只返回公共方法,因此不会做我想做的事; 仅返回当前类的方法。虽然我当然可以使用后者并手动检查类层次结构以检查可见性规则,但如果没有更好的解决方案,我宁愿不这样做。我在这里错过了一些明显的东西吗?Class.getMethods()Class.getDeclaredMethods()


答案 1

使用 Class.getDeclaredMethods() 从类或接口获取所有方法(私有方法或其他方法)的列表。

Class c = ob.getClass();
for (Method method : c.getDeclaredMethods()) {
  if (method.getAnnotation(PostConstruct.class) != null) {
    System.out.println(method.getName());
  }
}

注意:这不包括继承的方法。为此,请使用 Class.getMethods()。它将返回所有公共方法(继承与否)。

若要对类可以访问的所有内容(包括继承的方法)进行全面列出,需要遍历它扩展的类的树。所以:

Class c = ob.getClass();
for (Class c = ob.getClass(); c != null; c = c.getSuperclass()) {
  for (Method method : c.getDeclaredMethods()) {
    if (method.getAnnotation(PostConstruct.class) != null) {
      System.out.println(c.getName() + "." + method.getName());
    }
  }
}

答案 2

正如cletus和PSpeed已经回答的那样 - 你需要遍历类的继承树。

这就是我这样做的方式,但不处理包私有方法:

public static Method[] getAccessibleMethods(Class clazz) {
   List<Method> result = new ArrayList<Method>();

   while (clazz != null) {
      for (Method method : clazz.getDeclaredMethods()) {
         int modifiers = method.getModifiers();
         if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) {
            result.add(method);
         }
      }
      clazz = clazz.getSuperclass();
   }

   return result.toArray(new Method[result.size()]);
}

我在向后兼容性检查器中使用它,我知道可能受影响的类无论如何都不会在同一包中。