小智 298
从技术上讲,这将有效......
String name = new Object(){}.getClass().getEnclosingMethod().getName();
Run Code Online (Sandbox Code Playgroud)
但是,将在编译期间创建一个新的匿名内部类(例如YourClass$1.class).因此,这将为.class部署此技巧的每个方法创建一个文件.另外,在运行时期间在每次调用时创建否则未使用的对象实例.所以这可能是一个可接受的调试技巧,但它确实带来了巨大的开销.
这个技巧的一个优点是可以用来检索方法的所有其他信息的getEncosingMethod()返回java.lang.reflect.Method,包括注释和参数名称.这使得可以区分具有相同名称的特定方法(方法过载).
注意,根据JavaDoc的getEnclosingMethod()这个技巧不应该抛出一个SecurityException内部类应该使用相同的类加载器加载.因此,即使存在安全管理器,也无需检查访问条件.
它需要getEnclosingConstructor()用于构造函数.在(命名)方法之外的块期间,getEnclosingMethod()返回null.
Bom*_*mbe 171
Thread.currentThread().getStackTrace().Thread.currentThread().getStackTrace().Thread.currentThread().getStackTrace()通常会包含你从中调用它的方法,但是有一些陷阱(参见Javadoc):
在某些情况下,某些虚拟机可能会从堆栈跟踪中省略一个或多个堆栈帧.在极端情况下,允许没有关于此线程的堆栈跟踪信息的虚拟机从此方法返回零长度数组.
Von*_*onC 135
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
}
Run Code Online (Sandbox Code Playgroud)
更多关于这个问题.
2011年12月更新:
蓝色评论:
我使用JRE 6并给出了错误的方法名称.
如果我写的话它会起作用ste[2 + depth].getMethodName().
0是的getStackTrace(),1是getMethodName(int depth)和2正在调用方法.
virgo47的回答(upvoted)实际上计算了要应用的正确索引以便取回方法名称.
vir*_*o47 83
我们使用此代码来缓解堆栈跟踪索引中的潜在可变性 - 现在只需调用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();
}
}
Run Code Online (Sandbox Code Playgroud)
似乎过度工程,但我们有一些JDK 1.5的固定数字,当我们转移到JDK 1.6时,它有点意外.现在它在Java 6/7中是相同的,但你永远不会知道.它不能证明在运行时期间该索引的更改 - 但希望HotSpot不会那么糟糕.:-)
ale*_*ail 45
public class SomeClass {
public void foo(){
class Local {};
String name = Local.class.getEnclosingMethod().getName();
}
}
Run Code Online (Sandbox Code Playgroud)
名称将具有值foo.
Cha*_*man 33
这两个选项都适用于Java:
new Object(){}.getClass().getEnclosingMethod().getName()
Run Code Online (Sandbox Code Playgroud)
要么:
Thread.currentThread().getStackTrace()[1].getMethodName()
Run Code Online (Sandbox Code Playgroud)
mak*_*enz 32
我找到的最快的方法是:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
它直接访问本机方法getStackTraceElement(int depth).并将可访问的Method存储在静态变量中.
Sum*_*ngh 25
使用以下代码:
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
String methodName = e.getMethodName();
System.out.println(methodName);
Run Code Online (Sandbox Code Playgroud)
小智 16
public static String getCurrentMethodName() {
return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
}
Run Code Online (Sandbox Code Playgroud)
mva*_*nle 14
这是对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 + ")";
}
}
Run Code Online (Sandbox Code Playgroud)
Fri*_*ade 12
要获取调用当前方法的方法的名称,您可以使用:
new Exception("is not thrown").getStackTrace()[1].getMethodName()
Run Code Online (Sandbox Code Playgroud)
这适用于我的MacBook以及我的Android手机
我也尝试过:
Thread.currentThread().getStackTrace()[1]
Run Code Online (Sandbox Code Playgroud)
但Android将返回"getStackTrace"我可以用Android修复此问题
Thread.currentThread().getStackTrace()[2]
Run Code Online (Sandbox Code Playgroud)
但后来我在MacBook上得到了错误的答案
Max*_*ple 11
Util.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();
}
Run Code Online (Sandbox Code Playgroud)
SomeClass.java:
public class SomeClass {
public static void main(String[] args) {
System.out.println(Util.getCurrentClassAndMethodNames()); // output: SomeClass.main
}
}
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
StackWalker被设计为懒惰的,所以它可能比Thread.getStackTrace为整个调用栈急切创建一个数组的效率更高。另请参阅JEP以获取更多信息。
一种替代方法是创建但不引发Exception,并使用该对象从中获取堆栈跟踪数据,因为包围方法通常位于索引0处,只要JVM存储该信息即可,其他方法也是如此上文提到的。但是,这不是最便宜的方法。
从Throwable.getStackTrace()(至少从Java 5开始,这是相同的):
数组的第零个元素(假设数组的长度为非零)表示栈顶,这是序列中的最后一个方法调用。通常,这是创建和抛出该throwable的地方。
下面的代码段假定类是非静态的(由于getClass()),但这是一个问题。
System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
Run Code Online (Sandbox Code Playgroud)