问题 Java:获取当前正在执行的Method对应的对象


将当前正在执行的方法作为Method对象的最优雅方法是什么?

我的第一个显而易见的方法是在helper类中使用静态方法,它将加载当前线程堆栈,获取正确的堆栈跟踪元素,并根据其信息构造Method元素。

是否有更优雅的方式来实现这一目标?


2429
2018-02-28 09:10


起源

这方面的缺点是处理重载方法很复杂。我的建议是找到另一种方法来做你想做的事情而没有 Method 目的。你为什么需要它? - Peter Lawrey
可能值得查看一些需要执行此操作的日志API的源代码。其中一些项目已经存在了很长时间,应该有一些解决这个问题的方法 - magicduncan
@Peter:你是对的,但是我正在注释我需要找到的方法,所以不用担心重载。实际上动态地找到Method对象可以让我避免更糟糕的问题解决方案。 - glmxndr
@magicduncan:有趣的是,我能想到的所有日志框架都不是开箱即用的。 Log4J可以做到这一点(见 的PatternLayout的 %L 要么 %M 选项)但警告说这是 非常 慢,因为IIRC他们只是打电话 Thread.currentThread().getStackTrace() 同样。 - Andrzej Doyle
在Oracle的JVM中,您可以调用 sun.reflect.Reflection.getCallerClass(int) 这可以更高效,但依赖于平台,它不会为您提供方法。 - Peter Lawrey


答案:


开箱即用,我不知道有更好的方法来做到这一点。

要考虑的一件事可能是方面 - 您可以将一个方面编织到围绕所有方法调用的代码中并推送当前 Method 对象到ThreadLocal(基于可从连接点获得的反射信息)。

如果真的开火,这可能会非常昂贵 所有 方法,但取决于你对结果做了什么,你可能能够将捕获限制到某些包/类,这将有所帮助。您可以推迟实际的查找 Method 直到它被使用的时间为止,而是存储方法和参数的名称等。

不过,我怀疑是否会以一种特别便宜的方式实现这一目标。


2
2018-02-28 09:24





更深入地介绍了该主题 在这个SO问题中

我需要做同样的事情,我找到了最好的解决方案,成为@alexsmail提供的解决方案。

它似乎有点hacky但总的想法是你在方法中声明一个本地类,然后利用 class.getEnclosingMethod();

从@ alexsmail的解决方案略微修改的代码:

public class SomeClass {
   public void foo(){
      class Local {};
      Method m = Local.class.getEnclosingMethod();
   }
 }

14
2017-11-04 17:51



另一个简化版本可能是这样的:new Object(){}。getClass()。getEnclosingMethod() - Trevor Brown