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

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

例:

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级,我想得到:

  • 所有自己的方法
  • AA methodA1methodA2
  • methodA3当且仅当B类与A在同一个包中时

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

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

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

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

注意:这不包括inheritance的方法。 使用Class.getMethods() 。 它将返回所有公共方法(inheritance或不inheritance)。

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

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

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

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

 public static Method[] getAccessibleMethods(Class clazz) { List result = new ArrayList(); 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()]); } 

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

很确定你必须走上超级class才能得到你想要的东西。 毕竟,这就是getMethods()在内部使用getDeclaredMethods()调用的方式(实际上它调用了一个过滤掉非公共方法的私有版本,但它会遍历类树以构建完整列表)。

但是好奇为什么需要这样的东西。

关于Cletus答案的观点(我不能在那里发表评论,因为我没有足够的声誉。) 无论如何,Cletus的代码对我不起作用(Eclipse也在抱怨它),可能是由于自2009年以来Java的变化。

这条线:

 for (Class c = ob.getClass(); c != null; c = c.getSuperclass()) { 

不得不改为:

 for (Class c = ob.getClass(); c != null; c = c.getSuperclass()) { 

得到任何输出。 所以我的完整代码是(包括输入参数类型,修饰符和返回类型):

  for (Class c = scanner.getClass(); c != null; c = c.getSuperclass()) { System.out.println(c.getName()); for (Method method : c.getMethods()) { System.out.println("\t" + Modifier.toString(method.getModifiers()) + " " + method.getName()); for (Class param: method.getParameterTypes()) { System.out.println("\t\t" + param.getName()); } System.out.println("\t\t == returns ==> " + method.getReturnType().getName()); } }