Java 获取当前正在执行的方法的名称
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/442747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting the name of the currently executing method
提问by Omar Kooheji
Is there a way to get the name of the currently executing method in Java?
有没有办法在Java中获取当前正在执行的方法的名称?
采纳答案by Bombe
Thread.currentThread().getStackTrace()
will usually contain the method you're calling it from but there are pitfalls (see Javadoc):
Thread.currentThread().getStackTrace()
通常将包含您从中调用它的方法,但存在陷阱(请参阅Javadoc):
Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this thread is permitted to return a zero-length array from this method.
在某些情况下,某些虚拟机可能会从堆栈跟踪中省略一个或多个堆栈帧。在极端情况下,允许没有与此线程相关的堆栈跟踪信息的虚拟机从此方法返回零长度数组。
回答by VonC
January 2009:
A full code would be (to use with @Bombe's caveatin mind):
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
}
More in this question.
更多在这个问题。
Update December 2011:
2011 年 12 月更新:
bluishcomments:
蓝色评论:
I use JRE 6 and gives me incorrect method name.
It works if I writeste[2 + depth].getMethodName().
0
isgetStackTrace()
,1
isgetMethodName(int depth)
and2
is invoking method.
我使用 JRE 6 并给了我不正确的方法名称。
如果我写它会起作用ste[2 + depth].getMethodName().
0
是getStackTrace()
,1
是getMethodName(int depth)
和2
正在调用方法。
virgo47's answer(upvoted) actually computes the right index to apply in order to get back the method name.
回答by Devin
Technically this will work...
从技术上讲,这将起作用...
String name = new Object(){}.getClass().getEnclosingMethod().getName();
However, a new anonymous inner class will be created during compile time (e.g. YourClass$1.class
). So this will create a .class
file for each method that deploys this trick. Additionally an otherwise unused object instance is created on each invocation during runtime. So this may be an acceptable debug trick, but it does come with significant overhead.
但是,将在编译时创建一个新的匿名内部类(例如YourClass$1.class
)。因此,这将为.class
部署此技巧的每个方法创建一个文件。此外,在运行时每次调用时都会创建一个未使用的对象实例。所以这可能是一个可以接受的调试技巧,但它确实带来了巨大的开销。
An advantage of this trick is that getEncosingMethod()
returns java.lang.reflect.Method
which can be used to retrieve all other information of the method including annotations and parameter names. This makes it possible to distinguish between specific methods with the same name (method overload).
这个技巧的一个优点是getEncosingMethod()
返回java.lang.reflect.Method
可用于检索方法的所有其他信息,包括注释和参数名称。这使得可以区分具有相同名称的特定方法(方法重载)。
Note that according to the JavaDoc of getEnclosingMethod()
this trick should not throw a SecurityException
as inner classes should be loaded using the same class loader. So there is no need to check the access conditions even if a security manager is present.
请注意,根据getEnclosingMethod()
此技巧的 JavaDoc,不应抛出 a,SecurityException
因为应使用相同的类加载器加载内部类。因此,即使存在安全管理器,也无需检查访问条件。
It is required to use getEnclosingConstructor()
for constructors. During blocks outside of (named) methods, getEnclosingMethod()
returns null
.
需要getEnclosingConstructor()
用于构造函数。在(命名)方法之外的块期间,getEnclosingMethod()
返回null
.
回答by virgo47
We used this code to mitigate potential variability in stack trace index - now just call methodName util:
我们使用此代码来减轻堆栈跟踪索引中的潜在可变性 - 现在只需调用 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();
}
}
Seems overengineered, but we had some fixed number for JDK 1.5 and were a bit surprised it changed when we moved to JDK 1.6. Now it's the same in Java 6/7, but you just never know. It is not proof to changes in that index during runtime - but hopefully HotSpot doesn't do that bad. :-)
似乎设计过度,但我们为 JDK 1.5 设置了一些固定数字,当我们迁移到 JDK 1.6 时,它发生了变化,这让我们有点惊讶。现在它在 Java 6/7 中是一样的,但你永远不知道。这并不能证明运行时该索引的更改 - 但希望 HotSpot 不会做得那么糟糕。:-)
回答by Sumit Singh
Use the following Code :
使用以下代码:
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
String methodName = e.getMethodName();
System.out.println(methodName);
回答by Sumit Singh
The fastest wayI found is that:
我找到的最快的方法是:
import java.lang.reflect.Method;
public class TraceHelper {
// save it static to have it available on every call
private static Method m;
static {
try {
m = Throwable.class.getDeclaredMethod("getStackTraceElement",
int.class);
m.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getMethodName(final int depth) {
try {
StackTraceElement element = (StackTraceElement) m.invoke(
new Throwable(), depth + 1);
return element.getMethodName();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
It accesses the native method getStackTraceElement(int depth) directly. And stores the accessible Method in a static variable.
它直接访问本地方法 getStackTraceElement(int depth)。并将可访问的方法存储在静态变量中。
回答by mvanle
This is an expansion on virgo47's answer(above).
这是对virgo47 的回答(上图)的扩展。
It provides some static methods to get the current and invoking class / method names.
它提供了一些静态方法来获取当前和调用的类/方法名称。
/* Utility class: Getting the name of the current executing method
* https://stackoverflow.com/questions/442747/getting-the-name-of-the-current-executing-method
*
* Provides:
*
* getCurrentClassName()
* getCurrentMethodName()
* getCurrentFileName()
*
* getInvokingClassName()
* getInvokingMethodName()
* getInvokingFileName()
*
* Nb. Using StackTrace's to get this info is expensive. There are more optimised ways to obtain
* method names. See other stackoverflow posts eg. https://stackoverflow.com/questions/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection/2924426#2924426
*
* 29/09/2012 (lem) - added methods to return (1) fully qualified names and (2) invoking class/method names
*/
package com.stackoverflow.util;
public class StackTraceInfo
{
/* (Lifted from virgo47's stackoverflow answer) */
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(StackTraceInfo.class.getName()))
{
break;
}
}
CLIENT_CODE_STACK_INDEX = i;
}
public static String getCurrentMethodName()
{
return getCurrentMethodName(1); // making additional overloaded method call requires +1 offset
}
private static String getCurrentMethodName(int offset)
{
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getMethodName();
}
public static String getCurrentClassName()
{
return getCurrentClassName(1); // making additional overloaded method call requires +1 offset
}
private static String getCurrentClassName(int offset)
{
return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getClassName();
}
public static String getCurrentFileName()
{
return getCurrentFileName(1); // making additional overloaded method call requires +1 offset
}
private static String getCurrentFileName(int offset)
{
String filename = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getFileName();
int lineNumber = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getLineNumber();
return filename + ":" + lineNumber;
}
public static String getInvokingMethodName()
{
return getInvokingMethodName(2);
}
private static String getInvokingMethodName(int offset)
{
return getCurrentMethodName(offset + 1); // re-uses getCurrentMethodName() with desired index
}
public static String getInvokingClassName()
{
return getInvokingClassName(2);
}
private static String getInvokingClassName(int offset)
{
return getCurrentClassName(offset + 1); // re-uses getCurrentClassName() with desired index
}
public static String getInvokingFileName()
{
return getInvokingFileName(2);
}
private static String getInvokingFileName(int offset)
{
return getCurrentFileName(offset + 1); // re-uses getCurrentFileName() with desired index
}
public static String getCurrentMethodNameFqn()
{
return getCurrentMethodNameFqn(1);
}
private static String getCurrentMethodNameFqn(int offset)
{
String currentClassName = getCurrentClassName(offset + 1);
String currentMethodName = getCurrentMethodName(offset + 1);
return currentClassName + "." + currentMethodName ;
}
public static String getCurrentFileNameFqn()
{
String CurrentMethodNameFqn = getCurrentMethodNameFqn(1);
String currentFileName = getCurrentFileName(1);
return CurrentMethodNameFqn + "(" + currentFileName + ")";
}
public static String getInvokingMethodNameFqn()
{
return getInvokingMethodNameFqn(2);
}
private static String getInvokingMethodNameFqn(int offset)
{
String invokingClassName = getInvokingClassName(offset + 1);
String invokingMethodName = getInvokingMethodName(offset + 1);
return invokingClassName + "." + invokingMethodName;
}
public static String getInvokingFileNameFqn()
{
String invokingMethodNameFqn = getInvokingMethodNameFqn(2);
String invokingFileName = getInvokingFileName(2);
return invokingMethodNameFqn + "(" + invokingFileName + ")";
}
}
回答by alexsmail
public class SomeClass {
public void foo(){
class Local {};
String name = Local.class.getEnclosingMethod().getName();
}
}
name will have value foo.
名称将具有值 foo。
回答by ran
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);
回答by Jay
public static String getCurrentMethodName() {
return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
}