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


当前回答

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

其他回答

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

这是对virgo47的答案(如上)的扩展。

它提供了一些静态方法来获取当前和调用类/方法名。

/* 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 + ")";
    }
}
 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

Name的值为foo。

我不知道获取当前执行的方法名称背后的意图是什么,但如果只是为了调试目的,那么像“logback”这样的日志框架可以在这里提供帮助。例如,在logback中,您只需要在日志配置中使用模式“%M”。但是,应该谨慎使用,因为这可能会降低性能。

使用以下代码:

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