获取当前正在执行的方法的名称

Getting the name of the currently executing method

提问人:Omar Kooheji 提问时间:1/14/2009 最后编辑:Kedar MhaswadeOmar Kooheji 更新时间:8/7/2023 访问量:471274

问:

有没有办法在Java中获取当前正在执行的方法的名称?

Java 反射 方法

评论

1赞 Honza Zidek 6/15/2023
我认为现在(从 Java 9 开始)公认的答案应该是 .你很久以前接受的答案现在已经过时了。StackWalker
1赞 Basil Bourque 7/24/2023
请参阅此 Answer 中的现代 java.lang.StackWalker 解决方案。

答:

203赞 Bombe 1/14/2009 #1

Thread.currentThread().getStackTrace()通常包含您从中调用它的方法,但存在一些陷阱(参见 Javadoc):

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

评论

7赞 Nate Parsons 3/4/2009
对于异常中的堆栈跟踪,是否也存在同样的陷阱?
8赞 Bombe 11/12/2011
是的,它是。Throwable 的文档。[getStackTrace()](download.oracle.com/javase/1.5.0/docs/api/java/lang/...包含完全相同的段落。
4赞 Thorbjørn Ravn Andersen 4/15/2013
最根本的一点是,JVM不需要能够提供堆栈跟踪,但是为了让HotSpot非常可靠,已经做了很多工作。但是,您需要知道,如果您希望您的代码不依赖于特定 JVM 的行为。
0赞 Gus 7/7/2013
下面的 Alexsmail 版本没有创建堆栈跟踪,而是允许您访问实际的方法对象,而不仅仅是名称(因此您也可以找到返回类型)。我没有做过基准标记,但我怀疑他的方法也快得多,因为堆栈跟踪往往很昂贵。
142赞 VonC 1/14/2009 #2

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().

  • 0getStackTrace()
  • 1是和getMethodName(int depth)
  • 2正在调用方法。

Virgo47答案(点赞)实际上计算了要应用的正确索引,以便取回方法名称。

评论

2赞 Prof. Falken 5/25/2011
它只对我说“主要”。:-/
0赞 VonC 5/25/2011
@Amigable:您是否尝试打印所有数组以进行调试,并查看“main”是否真的是正确的方法?StackTraceElement
7赞 bluish 12/28/2011
我使用 JRE 6 并给了我不正确的方法名称。如果我写,它就会起作用.0 是 ,1 是 ,2 是调用方法。另请参阅@virgo47的回答ste[2 + depth].getMethodName()getStackTrace()getMethodName(int depth)
2赞 VonC 12/29/2011
@bluish:好点子。我已经在我的评论中加入了你的评论和对 virgo47 答案的引用。
0赞 mjs 3/29/2020
@VonC 这个实现真的正确吗?这里的深度必须是 ste.length + 1 才能给出当前方法。如果我们要允许深度 = 0,它不应该是 ste[depth + 1] 吗?
360赞 Devin 5/5/2011 #3

从技术上讲,这将起作用......

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

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

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

请注意,根据这个技巧的 JavaDoc 不应该抛出一个,因为内部类应该使用相同的类加载器加载。因此,即使存在安全管理器,也无需检查访问条件。getEnclosingMethod()SecurityException

请注意:它需要用于构造函数。在(命名)方法之外的块期间,返回 .getEnclosingConstructor()getEnclosingMethod()null

评论

10赞 shrini1000 5/4/2012
这不会给你当前正在执行的方法。这将为您提供定义匿名/本地类的方法。- docs.oracle.com/javase/6/docs/api/java/lang/......
7赞 alexsmail 3/13/2013
class 本地 {};字符串名称 = 本地.class.getEnclosingMethod().getName();
26赞 Thorbjørn Ravn Andersen 4/15/2013
@shrini1000的想法是在需要信息的地方使用此代码片段,而不是将其放在库例程中。
4赞 Lilo 3/27/2015
谢谢你的提示!无需创建新对象,只需使用 this.getClass().getEnclosingMethod().getName();
4赞 Hazel T 9/21/2017
@Lilo不正确。 获取定义类的方法的名称。 对你一点帮助都没有。@wutzebaer你为什么还需要呢?您已经可以访问它们。getEnclosingMethodthis.getClass()
92赞 virgo47 12/22/2011 #4

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

评论

2赞 Thorbjørn Ravn Andersen 4/15/2013
这仍然微妙地依赖于供应商。JVM 不需要为此代码提供可靠的数据。
7赞 Thorbjørn Ravn Andersen 4/16/2013
根据 JVM 规范,JVM 不需要提供完整的堆栈跟踪(优化、内联等),并且您已经发现您的启发式方法在 Oracle Java 5 和 Oracle Java 6 之间发生了变化。没有任何东西可以保证任何其他 JVM 的行为都符合您在代码中的期望,因此您巧妙地依赖于供应商特定的行为。只要您意识到这一点,这完全没问题,但是如果 - 例如 - 您需要部署在 IBM JVM(我们必须)或 Zing 实例上,您可能需要重新审视您的启发式方法。
1赞 Ian 3/4/2018
这似乎是这里介绍的所有选项中最强大的,尽管存在依赖关系。
24赞 Sumit Singh 6/12/2012 #5

使用以下代码:

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

评论

2赞 Zack Macomber 2/6/2013
这为我打印了“getStackTrace” - 我正在使用 Java 1.5
0赞 el-teedee 2/28/2018
根据 Bombe 的答案和 javadoc 指示小心空数组。某些 JVM 可能无法填充堆栈跟踪数组?
35赞 user1563700 7/31/2012 #6

最快的方式我发现:

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;
        }
    }
}

它直接访问本机方法 getStackTraceElement(int depth)。并将可访问的 Method 存储在静态变量中。

评论

3赞 Ibrahim Arief 8/24/2012
在性能方面最快?有什么微观基准来支持这一说法吗?
10赞 ach 1/26/2013
+1.在 1.6 上使用简单的定时循环,使用这种方法进行 1,000,000 次迭代需要 1219 毫秒,而使用需要 5614 毫秒。new Throwable().getStackTrace()
1赞 avanderw 1/23/2014
m.setAccessible(真);应被 AccessController.doPrivileged 包围。要考虑的事情,我想说的不是硬性规定
6赞 Ryan 7/1/2016
在 2016 年进行了测试,这仍然是最快的。像@ach一样,我使用了 1M 迭代。1.7_79:1.6 秒对 15.2 秒 1.8_74:1.8 秒对 16.0 秒。FWIW 我的基准 ste 阵列的长度==23,但无论堆栈深度如何,此方法都保持快速。
1赞 Holger 5/17/2023
@Dennie即使有这种方法,现在也会失败。setAccessible(true)
14赞 mvanle 9/29/2012 #7

这是对 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 + ")";
    }
}

评论

3赞 Octavia Togami 7/27/2013
这与 @mklemenz 的答案相结合,是一种非常快速和干净的方式来访问堆栈信息。
48赞 alexsmail 3/13/2013 #8
 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

name 的值为 foo。

评论

6赞 eigil 11/29/2013
Local.class.getEnclosingMethod() 为 null。jdk1.6.0_31,玩 1.2.5
0赞 Maarten Bodewes 4/15/2014
@eigil这很有趣,但如果没有更多信息,很难说出出了什么“问题”或我们应该期待什么null
0赞 Maarten Bodewes 4/15/2014
这与这个答案是一样的技巧。它的优点是它不会创建虚假对象实例,它的缺点是它需要一个不能在语句中内联的类声明(即通常它需要一行额外的代码)。
0赞 D.N. 3/11/2015
您@eigil在类(例如 SomeClass)中还是在方法(例如 foo)中定义了类?我发现在不包装在方法或构造函数中的情况下定义子类将导致 getEnclosingMethod() 返回 null。
0赞 eigil 3/26/2015
可以肯定的是,我完全按照这个答案中的描述做了。我认为这对游戏框架来说很奇怪。在“普通”java中测试,没有任何问题。
4赞 ran 6/3/2013 #9
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);

评论

1赞 alexsmail 7/7/2013
请参阅上面 mvanle virgo47 的答案和 thorbjorn-ravn-andersen 的评论。重复、不准确和不可靠的代码。
0赞 Maarten Bodewes 4/15/2014
@ShivaKomuravelly 是的,但似乎在任何情况下都不是,所以我也是 -1。
20赞 Jay 2/19/2014 #10
public static String getCurrentMethodName() {
        return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
    }

评论

0赞 mike rodent 10/23/2016
是的,到目前为止最好的......将其转换为方法,并获取跟踪中的第三个 ([2]) 帧(或它的名称)。
1赞 Holger 5/17/2023
不要重复自己。尤其是当重复表达式非常昂贵时,例如 .这就是局部变量的用途,用于存储评估结果,以便您可以多次使用结果,而不是重复评估。Thread.currentThread().getStackTrace()
5赞 Jool 12/15/2014 #11

另一种方法是创建(但不抛出)异常,并使用该对象从中获取堆栈跟踪数据,因为封闭方法通常位于索引 0 处 - 只要 JVM 存储该信息,正如上面提到的其他人一样。然而,这并不是最便宜的方法。

来自 Throwable.getStackTrace()(至少从 Java 5 开始就是这样):

数组的第 0 个元素(假设数组的长度不为零)表示堆栈的顶部,这是序列中的最后一个方法调用。通常,这是创建和投掷此可投掷物的点。

下面的代码片段假设该类是非静态的(因为 getClass()),但这是题外话。

System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
48赞 Charlie S 9/1/2015 #12

这两个选项都适用于我的 Java:

new Object(){}.getClass().getEnclosingMethod().getName()

艺术

Thread.currentThread().getStackTrace()[1].getMethodName()

评论

1赞 jellobird 5/31/2017
对于静态方法,请使用:<Class>.class.getEnclosingMethod().getName()
0赞 el-teedee 2/28/2018
根据 Bombe 的答案和 javadoc 指示小心空数组。某些 JVM 可能无法填充堆栈跟踪数组?
12赞 Friso van der Made 9/22/2015 #13

若要获取调用当前方法的方法的名称,可以使用:

new Exception("is not thrown").getStackTrace()[1].getMethodName()

这适用于我的 MacBook 和我的 Android 手机

我也试过:

Thread.currentThread().getStackTrace()[1]

但 Android 将返回“getStackTrace” 我可以用 Android 解决这个问题

Thread.currentThread().getStackTrace()[2]

但后来我在MacBook上得到了错误的答案

评论

0赞 mbm29414 3/21/2016
在最近在 Android 上的测试中,它对我来说更好用,而不是.YMMV。getStackTrace()[0]getStackTrace()[1]
0赞 Ninja 10/17/2017
适用于 Android 的 UP 是Thread.currentThread().getStackTrace()[2]
11赞 Maxple 11/2/2015 #14

实用程序.java:

public static String getCurrentClassAndMethodNames() {
    final StackTraceElement e = Thread.currentThread().getStackTrace()[2];
    final String s = e.getClassName();
    return s.substring(s.lastIndexOf('.') + 1, s.length()) + "." + e.getMethodName();
}

SomeClass.java:

public class SomeClass {
    public static void main(String[] args) {
        System.out.println(Util.getCurrentClassAndMethodNames()); // output: SomeClass.main
    }
}

评论

0赞 Marks 11/26/2015
final StackTraceElement e = Thread.currentThread().getStackTrace()[2]; 工程; 返回完整的类名并返回 methon 名称。e.getClassName();e.getMethodName()
2赞 PhilLab 7/14/2017
getStackTrace()[2]是错误的,一定是因为: [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3] 调用这个的函数 a()getStackTrace()[3]
3赞 Kasim Rangwala 3/3/2016 #15

我有使用它的解决方案(在 Android 中)

/**
 * @param className       fully qualified className
 *                        <br/>
 *                        <code>YourClassName.class.getName();</code>
 *                        <br/><br/>
 * @param classSimpleName simpleClassName
 *                        <br/>
 *                        <code>YourClassName.class.getSimpleName();</code>
 *                        <br/><br/>
 */
public static void getStackTrace(final String className, final String classSimpleName) {
    final StackTraceElement[] steArray = Thread.currentThread().getStackTrace();
    int index = 0;
    for (StackTraceElement ste : steArray) {
        if (ste.getClassName().equals(className)) {
            break;
        }
        index++;
    }
    if (index >= steArray.length) {
        // Little Hacky
        Log.w(classSimpleName, Arrays.toString(new String[]{steArray[3].getMethodName(), String.valueOf(steArray[3].getLineNumber())}));
    } else {
        // Legitimate
        Log.w(classSimpleName, Arrays.toString(new String[]{steArray[index].getMethodName(), String.valueOf(steArray[index].getLineNumber())}));
    }
}
-2赞 Darren 9/27/2016 #16
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();

评论

13赞 abarisone 9/27/2016
请编辑更多信息。不鼓励使用纯代码和“尝试此”答案,因为它们不包含可搜索的内容,并且不解释为什么有人应该“尝试此操作”。
1赞 Toby Speight 9/28/2016
尽管此代码可能有助于解决问题,但它没有解释为什么和/或如何回答问题。提供这种额外的背景将大大提高其长期教育价值。请编辑您的答案以添加解释,包括适用的限制和假设。
1赞 Benj 10/11/2016
仅适用于 Java 7+,但获取方法名称的简洁方法。尽管如此,这种调用的性能考虑因素仍然存在。
7赞 Markus L 4/7/2017
getEnclosingMethod()在 Java 7 中为我抛出一个。NullPointerException
2赞 stove 4/25/2018
java.lang.Class.getEnclosingMethod() 返回一个 Method 对象,表示基础类的立即封闭方法,如果此 Class 对象表示方法中的本地或匿名类,则返回 null。
3赞 James Selvakumar 11/8/2016 #17

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

3赞 Egl 2/20/2018 #18

以防万一您想知道的名称方法是 junit 测试方法,那么您可以使用 junit TestName 规则:https://stackoverflow.com/a/1426730/3076107

评论

1赞 EJoshuaS - Stand with Ukraine 5/28/2019
@AndreiKonstantinov我不认为这是仅链接的。即使您删除了链接,至少还有一些信息可以继续。
43赞 Radiodef 9/14/2018 #19

java.lang.StackWalker, 爪哇 9+

从 Java 9 开始,这可以使用 StackWalker 来完成。

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被设计为懒惰,因此它可能比急切地为整个调用堆栈创建数组更有效。另请参阅 JEP 了解更多信息。Thread.getStackTrace

评论

3赞 Honza Zidek 6/15/2023
现在应该是公认的答案。
0赞 Sasha Kolsky 9/28/2023
对我有用,但使用 skip(0) - 用于当前方法
0赞 Marco Sulla 9/21/2019 #20

我稍微重写了 maklemenz 的答案

private static Method m;

static {
    try {
        m = Throwable.class.getDeclaredMethod(
            "getStackTraceElement",
            int.class
        );
    }
    catch (final NoSuchMethodException e) {
        throw new NoSuchMethodUncheckedException(e);
    }
    catch (final SecurityException e) {
        throw new SecurityUncheckedException(e);
    }
}


public static String getMethodName(int depth) {
    StackTraceElement element;

    final boolean accessible = m.isAccessible();
    m.setAccessible(true);

    try {
        element = (StackTraceElement) m.invoke(new Throwable(), 1 + depth);
    }
    catch (final IllegalAccessException e) {
        throw new IllegalAccessUncheckedException(e);
    }
    catch (final InvocationTargetException e) {
        throw new InvocationTargetUncheckedException(e);
    }
    finally {
        m.setAccessible(accessible);
    }

    return element.getMethodName();
}

public static String getMethodName() {
    return getMethodName(1);
}

1赞 mjs 3/29/2020 #21

这里的大多数答案似乎都是错误的。

    public static String getCurrentMethod() {
            return getCurrentMethod(1);
    }
    public static String getCurrentMethod(int skip) {
            return Thread.currentThread().getStackTrace()[1 + 1 + skip].getMethodName();
    }

例:

    public static void main(String[] args) {
            aaa();
    }

    public static void aaa() {
            System.out.println("aaa  -> "  + getCurrentMethod( ) );
            System.out.println("aaa  -> "  + getCurrentMethod(0) );
            System.out.println("main -> "  + getCurrentMethod(1) );
    }

输出:

aaa  -> aaa
aaa  -> aaa
main -> main

评论

3赞 Xobotun 5/6/2020
您能否澄清一下为什么大多数答案对您来说似乎是错误的?有很多答案,我对 Java 不是很精通,无法阅读所有这些答案并了解它们和您的答案之间的区别。:(
4赞 Xobotun 5/11/2020
@mmm 对不起,但我强烈不同意。我相信,我来这里是为了学习,许多其他人也是如此。我只是不明白为什么你认为我不配在这个问题上了解更多。我想在我的代码中少犯错误,并警告其他人,不要追随一些货物崇拜。您至少可以澄清此代码在哪个 Java 版本上应该是正确的。:(下面的答案说堆栈跟踪在 1.5 和 1.6 之间发生了变化。也许你暗示在即将到来的 Java 14 中有类似的东西,我怎么知道。或者不同的供应商可能有。对不起,如果我把你的回答误解为粗鲁的回答。
3赞 fix 6/14/2021 #22

我将此代码片段与最新的 Android Studio 和最新的 Java 更新一起使用。它可以从任何 Activity、Fragment 等调用。

public static void logPoint() {
    String[] splitPath = Thread.currentThread().getStackTrace()[3]
        .toString().split("\\.");

    Log.d("my-log", MessageFormat.format("{0} {1}.{2}",
        splitPath[splitPath.length - 3],
        splitPath[splitPath.length - 2],
        splitPath[splitPath.length - 1]
    ));
}

这样称呼它

logPoint();

输出

... D/my-log: MainActivity onCreate[(MainActivity.java:44)]
1赞 Saikat 8/7/2023 #23

Java 9 或更高版本的首选解决方案:

private static String getCurrentMethodName() {
  return StackWalker.getInstance()
    .walk(frames -> frames.skip(1).findFirst().map(StackWalker.StackFrame::getMethodName))
    .orElse("Anything");
}

StackWalker有几个优点:

  • 无需创建虚拟匿名内部类实例,即new Object().getClass() {}
  • 无需急切地捕获整个堆栈跟踪,这可能代价高昂

这篇文章中阅读更多内容。