Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
请参阅调用方法的java注释_Java_Reflection_Annotations - Fatal编程技术网

请参阅调用方法的java注释

请参阅调用方法的java注释,java,reflection,annotations,Java,Reflection,Annotations,假设我遇到这样的情况: public String method(String s) { return stringForThisVisibility(s, EnumVisibility.PUBLIC); } @VisibilityLevel(value = EnumVisibility.PUBLIC) public String method(String s) { return stringForThisVisibility(s); } 我想用这样的注释替换它: publ

假设我遇到这样的情况:

public String method(String s) {
    return stringForThisVisibility(s, EnumVisibility.PUBLIC);
}
@VisibilityLevel(value = EnumVisibility.PUBLIC)
public String method(String s) {
    return stringForThisVisibility(s);
}
我想用这样的注释替换它:

public String method(String s) {
    return stringForThisVisibility(s, EnumVisibility.PUBLIC);
}
@VisibilityLevel(value = EnumVisibility.PUBLIC)
public String method(String s) {
    return stringForThisVisibility(s);
}
这似乎是一个更好、更清晰的解决方案,但我需要stringForThisVisibility方法通过某种反射来了解@VisibilityLevel的值。可能吗?我可以看到调用stringForThisVisibility的方法上的注释吗?

可以。 类似于

StackTraceElement[] stack = Thread.currentThread().getStackTrace();
Class callerClass = Class.forName(stack[stack.length-2].getClassName());
callerClass.isAnnotationPresent(...)
上面的代码查找类上的注释。您可以组合类名和方法名(也可以来自堆栈跟踪元素),然后查看方法。请注意,这非常慢。

您需要获取表示调用
stringForThisVisibility的方法的对象。不幸的是,Java没有提供这种现成的功能

但是,我们仍然可以通过返回的信息获得
方法
。该方法返回一个对象数组。每个
stackTraceeElement
对象告诉我们三件事:

  • 类的名称()
  • 方法的名称()
  • 行号()
这可能需要一些实验,但您应该找到该数组中的哪个索引表示您感兴趣的方法(它可能是数组中的第一个、第二个或第三个
stackTraceeElement

获得所需的
StackTraceeElement
后,可以使用题为的问题中的技术获取其相应的
方法
对象。即使该类有多个方法使用该方法名,该技术仍将保留word。如果您不担心这种情况,可以使用更简单的技术


拥有
方法
对象后,只需调用以下类即可。

 /**
   * 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();
    }
  }
你可以说: 方法me=(新的Util.MethodNameHelper(){}).getMethod()


我在该类中广泛使用了getName()调用。在我的机器上,这些匿名类实例化加上方法调用往往需要花费1500纳秒。在我的性能测试中,StackElement步行方法在我的机器上的成本大约是30倍(47000 ns)

这也是我知道的唯一解决办法。并不是说它不能保证在所有情况下都能工作:如果加载被调用类的类加载器不知道调用类(并且它的父类加载器都不知道),那么对
class.forName()
的调用将失败。这种技术是脆弱的(如果您的方法不是直接从带注释的方法调用的,该怎么办?您需要在堆栈中循环。如果注释在超类方法上而不是直接在调用方法上,该怎么办?您需要在超类上循环…)如果Philipp是对的,它可能会在复杂环境中出错(j2ee?osgi?)。它的速度也非常慢。您可以选择使用ThreadLocal标记的解决方案,并在调用该方法之前设置标记,但这看起来也很奇怪。如果您能准确描述您要做的事情,可能会找到一个优雅的解决方案