是否有一种方法来获得Java中当前正在执行的方法的名称?
当前回答
这可以使用StackWalker自Java 9。
public static String getCurrentMethodName() {
return StackWalker.getInstance()
.walk(s -> s.skip(1).findFirst())
.get()
.getMethodName();
}
public static String getCallerMethodName() {
return StackWalker.getInstance()
.walk(s -> s.skip(2).findFirst())
.get()
.getMethodName();
}
StackWalker被设计成懒惰的,所以它可能比Thread更有效。getStackTrace,它为整个调用堆栈急切地创建一个数组。更多信息请参见JEP。
其他回答
我们使用这段代码来减少堆栈跟踪索引的潜在可变性-现在只需调用methodName util:
public class MethodNameTest {
private static final int CLIENT_CODE_STACK_INDEX;
static {
// Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
int i = 0;
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
i++;
if (ste.getClassName().equals(MethodNameTest.class.getName())) {
break;
}
}
CLIENT_CODE_STACK_INDEX = i;
}
public static void main(String[] args) {
System.out.println("methodName() = " + methodName());
System.out.println("CLIENT_CODE_STACK_INDEX = " + CLIENT_CODE_STACK_INDEX);
}
public static String methodName() {
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX].getMethodName();
}
}
似乎是过度设计了,但我们对JDK 1.5有一些固定的数字,当我们迁移到JDK 1.6时,它发生了变化,这有点令人惊讶。现在在Java 6/7中也是一样的,但你永远不会知道。它不能证明索引在运行时发生了变化——但希望HotSpot不会做得那么糟糕。: -)
2009年1月: 完整的代码将是(使用@Bombe的警告):
/**
* Get the method name for a depth in call stack. <br />
* Utility function
* @param depth depth in the call stack (0 means current method, 1 means call method, ...)
* @return method name
*/
public static String getMethodName(final int depth)
{
final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
//System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName());
// return ste[ste.length - depth].getMethodName(); //Wrong, fails for depth = 0
return ste[ste.length - 1 - depth].getMethodName(); //Thank you Tom Tresansky
}
更多关于这个问题。
2011年12月更新:
蓝色的评论:
我使用JRE 6,给我不正确的方法名。 如果我写ste[2 + depth]. getmethodname(),它就会起作用。 0是getStackTrace(), 1是getMethodName(int depth)和 2是调用方法。
Virgo47的答案(获得好评)实际上计算了要应用的正确索引,以获得方法名。
我不知道获取当前执行的方法名称背后的意图是什么,但如果只是为了调试目的,那么像“logback”这样的日志框架可以在这里提供帮助。例如,在logback中,您只需要在日志配置中使用模式“%M”。但是,应该谨慎使用,因为这可能会降低性能。
public class SomeClass {
public void foo(){
class Local {};
String name = Local.class.getEnclosingMethod().getName();
}
}
Name的值为foo。
另一种方法是创建(但不是抛出)一个Exception,并使用该对象从中获取堆栈跟踪数据,因为封闭方法通常位于索引0——只要JVM存储该信息,就像上面其他人提到的那样。然而,这并不是最便宜的方法。
从Throwable.getStackTrace()(这至少从Java 5开始是一样的):
数组的第0个元素(假设数组的长度非零)表示堆栈的顶部,这是序列中的最后一个方法调用。通常,这是这个throwable被创建和抛出的点。
下面的代码片段假设该类是非静态的(因为getClass()),但这只是题外话。
System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
推荐文章
- .NET反射的成本有多高?
- 指定的子节点已经有一个父节点。你必须先在子对象的父对象上调用removeView() (Android)
- 对于一个布尔字段,它的getter/setter的命名约定是什么?
- 如何获得当前屏幕方向?
- 如何在Android中渲染PDF文件
- 如何计算一个元素在列表中出现的次数
- c++中类似于java的instanceof
- 我如何解决错误“minCompileSdk(31)指定在一个依赖的AAR元数据”在本机Java或Kotlin?
- 如何POST表单数据与Spring RestTemplate?
- Mockito中检测到未完成的存根
- 我应该如何复制字符串在Java?
- “while(true)”循环有那么糟糕吗?
- 这个方法签名中的省略号(…)是干什么用的?
- Java:如何测试调用System.exit()的方法?
- 带有返回类型的Java方法在没有返回语句的情况下编译