是否有一种方法来获得Java中当前正在执行的方法的名称?


当前回答

另一种方法是创建(但不是抛出)一个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());

其他回答

我们使用这段代码来减少堆栈跟踪索引的潜在可变性-现在只需调用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不会做得那么糟糕。: -)

从技术上讲,这是可行的……

String name = new Object(){}.getClass().getEnclosingMethod().getName();

但是,在编译时将创建一个新的匿名内部类(例如YourClass$1.class)。这将为每个部署这个技巧的方法创建一个。class文件。此外,在运行时的每次调用上都会创建一个未使用的对象实例。因此,这可能是一个可接受的调试技巧,但它确实带来了巨大的开销。

这种技巧的一个优点是getEnclosingMethod()返回java.lang.reflect.Method,该方法可用于检索方法的所有其他信息,包括注释和参数名。这使得区分具有相同名称的特定方法成为可能(方法重载)。

注意,根据getEnclosingMethod()的JavaDoc,这个技巧不应该抛出SecurityException,因为内部类应该使用相同的类装入器装入。因此,即使有安全管理人员在场,也不需要检查访问条件。

请注意:对于构造函数,必须使用getEnclosingConstructor()。在(命名)方法之外的块中,getEnclosingMethod()返回null。

Thread.currentThread().getStackTrace()通常会包含你调用它的方法,但有陷阱(参见Javadoc):

在某些情况下,一些虚拟机可能会从堆栈跟踪中省略一个或多个堆栈帧。在极端情况下,允许没有关于此线程的堆栈跟踪信息的虚拟机从此方法返回零长度数组。

String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);

使用以下代码:

    StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
    StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
    String methodName = e.getMethodName();
    System.out.println(methodName);