Java로 현재 실행중인 메소드의 이름을 얻는 방법이 있습니까?
답변
Thread.currentThread().getStackTrace()
일반적으로 호출하는 메소드를 포함하지만 함정이 있습니다 ( Javadoc 참조 ).
일부 가상 머신은 경우에 따라 스택 추적에서 하나 이상의 스택 프레임을 생략 할 수 있습니다. 극단적 인 경우,이 스레드에 관한 스택 추적 정보가없는 가상 머신은이 메소드에서 길이가 0 인 배열을 리턴 할 수 있습니다.
답변
기술적으로 이것은 작동합니다 …
String name = new Object(){}.getClass().getEnclosingMethod().getName();
그러나 컴파일 시간 동안 새로운 익명의 내부 클래스가 만들어집니다 (예 🙂 YourClass$1.class
. 따라서이 .class
트릭을 배포하는 각 방법에 대한 파일 이 생성됩니다 . 또한 런타임 동안 호출 할 때마다 사용하지 않는 객체 인스턴스가 생성됩니다. 따라서 이것은 허용 가능한 디버그 트릭 일 수 있지만 상당한 오버 헤드가 있습니다.
이 트릭의 장점은 주석 및 매개 변수 이름을 포함하여 메소드의 다른 모든 정보를 검색하는 데 사용할 수있는 getEncosingMethod()
리턴 java.lang.reflect.Method
입니다. 이를 통해 동일한 이름을 가진 특정 메소드 (방법 과부하)를 구별 할 수 있습니다.
getEnclosingMethod()
이 속임수 의 JavaDoc에 따르면 SecurityException
동일한 클래스 로더를 사용하여 내부 클래스를로드해야하므로 as를 던져서는 안됩니다. 따라서 보안 관리자가 있어도 액세스 조건을 확인할 필요가 없습니다.
getEnclosingConstructor()
생성자 에 사용해야 합니다. (명명 된) 메소드 외부의 블록 중에는을 getEnclosingMethod()
리턴합니다 null
.
답변
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().
0
입니다getStackTrace()
,1
이다getMethodName(int depth)
와2
메소드를 호출합니다.
virgo47 의 답변 ( 공개됨 )은 실제로 메소드 이름을 다시 얻기 위해 적용 할 올바른 색인을 계산합니다.
답변
이 코드를 사용하여 스택 추적 인덱스의 잠재적 변동성을 완화했습니다. 이제 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이 그렇게 나쁘지 않기를 바랍니다. 🙂
답변
public class SomeClass {
public void foo(){
class Local {};
String name = Local.class.getEnclosingMethod().getName();
}
}
name의 값은 foo입니다.
답변
이 두 가지 옵션 모두 Java에서 작동합니다.
new Object(){}.getClass().getEnclosingMethod().getName()
또는:
Thread.currentThread().getStackTrace()[1].getMethodName()
답변
내가 찾은 가장 빠른 방법 은 다음과 같습니다.
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)에 직접 액세스합니다. 그리고 접근 가능한 메소드를 정적 변수에 저장합니다.