简体   繁体   English

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

[英]Getting a list of accessible methods for a given class via reflection

Is there a way to get a list of methods that would be accessible (not necessarily public) by a given class?有没有办法获得一个给定类可以访问(不一定是公共的)的方法列表? The code in question will be in a completely different class.有问题的代码将在一个完全不同的类中。

Example:例子:

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

For class B I'd like to get:对于B类,我想得到:

  • all of its own methods所有它自己的方法
  • methodA1 and methodA2 from class A来自AA methodA1methodA2
  • methodA3 if and only if class B is in the same package as A methodA3当且仅当类BA在同一个包中

methodA4 should never be included in results because it's inaccessible to class B . methodA4永远不应包含在结果中,因为B类无法访问它。 To clarify once again, code that needs to find and return the above methods will be in a completely different class / package.再次澄清,需要查找和返回上述方法的代码将位于完全不同的类/包中。

Now, Class.getMethods() only returns public methods and thus won't do what I want;现在, Class.getMethods()只返回公共方法,因此不会做我想做的事; Class.getDeclaredMethods() only returns methods for current class. Class.getDeclaredMethods()只返回当前类的方法。 While I can certainly use the latter and walk the class hierarchy up checking the visibility rules manually, I'd rather not if there's a better solution.虽然我当然可以使用后者并手动检查类层次结构,但如果有更好的解决方案,我宁愿不这样做。 Am I missing something glaringly obvious here?我在这里遗漏了一些明显的东西吗?

Use Class.getDeclaredMethods() to get a list of all methods (private or otherwise) from the class or interface.使用Class.getDeclaredMethods()从类或接口获取所有方法(私有或其他)的列表。

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

Note: this excludes inherited methods.注意:这不包括继承的方法。 Use Class.getMethods() for that.为此使用Class.getMethods() It will return all public methods (inherited or not).它将返回所有公共方法(继承与否)。

To do a comprehensive list of everything a class can access (including inherited methods), you will need to traverse the tree of classes it extends.要完整列出一个类可以访问的所有内容(包括继承的方法),您需要遍历它扩展的类树。 So:所以:

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

As cletus and PSpeed has already answered - you need to traverse the inheritance tree of classes.正如 cletus 和 PSpeed 已经回答的那样 - 您需要遍历类的继承树。

This is the way I do it, but without handling package private methods:这是我这样做的方式,但不处理包私有方法:

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

I am using it in a backwards-compatibility checker where I know that the classes that might be affected will not be in the same package anyway.我在向后兼容性检查器中使用它,我知道可能受影响的类无论如何都不会在同一个包中。

Pretty sure you will have to walk up the superclass es to get what you want.很确定你将不得不走上superclass es 才能得到你想要的东西。 After all, that's what getMethods() is doing with the getDeclaredMethods() call internally (sort of... it actually calls a private version that filters out non- public methods but it does traverse up the class tree to build the full list).毕竟,这就是getMethods()在内部对getDeclaredMethods()调用所做的事情(有点……它实际上调用了一个过滤掉非public方法的private版本,但它确实遍历了class树以构建完整列表) .

Curious why such a thing is needed, though.不过很好奇为什么需要这样的东西。

A point on Cletus's answer (I can't comment there because I don't have enough reputation.).关于 Cletus 的回答的一点(我无法在那里发表评论,因为我没有足够的声誉。)。 Anyway, Cletus's code did not work for me (Eclipse was also complaining about it), probably due to changes in Java since 2009.无论如何,Cletus 的代码对我不起作用(Eclipse 也在抱怨它),可能是由于自 2009 年以来 Java 的变化。

The line:线路:

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

had to be changed to:必须改为:

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

to get any output at all.获得任何输出。 So the complete code for me was (including input argument types, modifiers and return type):所以对我来说完整的代码是(包括输入参数类型、修饰符和返回类型):

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

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

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