代码之家  ›  专栏  ›  技术社区  ›  ChssPly76

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

  •  27
  • ChssPly76  · 技术社区  · 15 年前

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

    例子:

    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 methodA2 从班上 A
    • methodA3 如果且仅当类 与在同一个包中

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

    现在, Class.getMethods() 只返回公共方法,因此不会执行我想要的操作; Class.getDeclaredMethods() 仅返回当前类的方法。虽然我当然可以使用后一种方法,手动检查可见性规则,但如果有更好的解决方案,我宁愿不使用。我是否遗漏了一些显而易见的东西?

    4 回复  |  直到 7 年前
        1
  •  33
  •   Cœur Gustavo Armenta    7 年前

    使用 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
  •  6
  •   ישו אוהב אותך Mahavir    8 年前

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

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

        3
  •  2
  •   PSpeed    15 年前

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

    奇怪的是,为什么需要这样的东西。

        4
  •  1
  •   Alluir    8 年前

    关于克莱特斯的回答(我不能评论,因为我没有足够的声誉)。无论如何,CelEts的代码对我来说不起作用(伊柯丽斯也在抱怨),可能是因为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());
          }
        }