请参阅调用方法的java注释

Fab*_*bio 6 java reflection annotations

假设我有这样的情况:

public String method(String s) {
    return stringForThisVisibility(s, EnumVisibility.PUBLIC);
}
Run Code Online (Sandbox Code Playgroud)

我想用这样的注释替换它:

@VisibilityLevel(value = EnumVisibility.PUBLIC)
public String method(String s) {
    return stringForThisVisibility(s);
}
Run Code Online (Sandbox Code Playgroud)

这似乎是一个更好,更清晰的解决方案,但我需要stringForThisVisibility方法来通过某种反射来了解@VisibilityLevel的值.那可能吗?我可以在调用stringForThisVisibility的方法上看到注释吗?

Jim*_*Jim 8

使用以下课程:

 /**
   * Proper use of this class is
   *     String testName = (new Util.MethodNameHelper(){}).getName();
   *  or
   *     Method me = (new Util.MethodNameHelper(){}).getMethod();
   * the anonymous class allows easy access to the method name of the enclosing scope.
   */
  public static class MethodNameHelper {
    public String getName() {
      final Method myMethod = this.getClass().getEnclosingMethod();
      if (null == myMethod) {
        // This happens when we are non-anonymously instantiated
        return this.getClass().getSimpleName() + ".unknown()"; // return a less useful string
      }
      final String className = myMethod.getDeclaringClass().getSimpleName();
      return className + "." + myMethod.getName() + "()";
    }

    public Method getMethod() {
      return this.getClass().getEnclosingMethod();
    }
  }
Run Code Online (Sandbox Code Playgroud)

可以调用:Method me =(new Util.MethodNameHelper(){}).getMethod();

我广泛使用该类中的getName()调用.在我的机器上,这些匿名类实例化和方法调用往往每个花费大约1500 ns.在我的性能测试中,StackElement行走方法在我的机器上花费了大约30倍(47000 ns).


rad*_*dai 6

是的,你可以.一些东西

StackTraceElement[] stack = Thread.currentThread().getStackTrace();
Class callerClass = Class.forName(stack[stack.length-2].getClassName());
callerClass.isAnnotationPresent(...)
Run Code Online (Sandbox Code Playgroud)

上面的代码在类上查找注释.您可以组合类名和方法名(也来自堆栈跟踪元素)并查看方法.请注意,这非常慢.

  • 这也是我所知道的唯一解决方案.并不是说它不能保证在所有情况下都能工作:如果加载被调用类的类加载器不知道调用类(并且它的父类加载器都不知道),对`Class.forName()`的调用将失败. (2认同)

Ada*_*ter 6

您需要获取Method表示调用方法的对象 stringForThisVisibility.不幸的是,Java并不提供开箱即用的功能.

但是,我们仍然可以Method通过返回的信息获取Thread.currentThread().getStackTrace().该方法返回一个StackTraceElement对象数组.每个StackTraceElement对象告诉我们三件事:

可能需要一些实验,但你应该找到该数组中的哪个索引代表你感兴趣的方法(它可能是StackTraceElement数组中的第一个,第二个或第三个).

StackTraceElement获得所需内容后,可以Method使用"获取调用者方法(java.lang.reflect.Method)"问题的答案中的技术获取其对应的对象.即使该类具有多个具有该方法名称的方法,该技术仍然会说出来.如果您不担心这种情况,可以使用更简单的技术.

一旦你拥有了这个Method对象,那只需要打电话method.getAnnotation(VisibilityLevel.class).