현재 실행중인 메소드의 이름 얻기


답변:


177

Thread.currentThread().getStackTrace()일반적으로 호출하는 메소드를 포함하지만 함정이 있습니다 ( Javadoc 참조 ).

일부 가상 머신은 경우에 따라 스택 추적에서 하나 이상의 스택 프레임을 생략 할 수 있습니다. 극단적 인 경우,이 스레드에 관한 스택 추적 정보가없는 가상 머신은이 메소드에서 길이가 0 인 배열을 리턴 할 수 있습니다.


7
예외의 스택 추적에도 동일한 함정이 적용됩니까?
네이트 파슨스

8
그렇습니다. Throwable . [getStackTrace ()] ( download.oracle.com/javase/1.5.0/docs/api/java/lang/…에 대한 문서
Bombe

4
근본적인 것은 JVM이 스택 트레이스를 제공 할 필요 는 없지만 HotSpot을 매우 안정적으로 만드는 많은 작업이 필요 하다는 것입니다 . 그러나 코드가 특정 JVM의 동작에 의존하지 않게하려면 알고 있어야합니다.
Thorbjørn Ravn Andersen

아래 Alexsmail 버전은 스택 추적을 생성하지 않으며 이름뿐만 아니라 실제 메소드 객체에 대한 액세스를 제공합니다 (따라서 리턴 유형도 찾을 수 있음). 나는 벤치 마크를하지 않았지만 스택 추적이 비싸기 때문에 그의 방법이 훨씬 빠르다고 생각합니다.
거스

Devin의 응답은이 질문에 훨씬 간결한 답변을 제공하는 것 같습니다.
risingTide

310

기술적으로 이것은 작동합니다 ...

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

그러나 컴파일 시간 동안 새로운 익명의 내부 클래스가 만들어집니다 (예 :) YourClass$1.class. 따라서이 .class트릭을 배포하는 각 방법에 대한 파일 이 생성됩니다 . 또한 런타임 동안 호출 할 때마다 사용하지 않는 객체 인스턴스가 생성됩니다. 따라서 이것은 허용 가능한 디버그 트릭 일 수 있지만 상당한 오버 헤드가 있습니다.

이 트릭의 장점은 주석 및 매개 변수 이름을 포함하여 메소드의 다른 모든 정보를 검색하는 데 사용할 수있는 getEncosingMethod()리턴 java.lang.reflect.Method입니다. 이를 통해 동일한 이름을 가진 특정 메소드 (방법 과부하)를 구별 할 수 있습니다.

getEnclosingMethod()이 속임수 의 JavaDoc에 따르면 SecurityException동일한 클래스 로더를 사용하여 내부 클래스를로드해야하므로 as를 던져서는 안됩니다. 따라서 보안 관리자가 있어도 액세스 조건을 확인할 필요가 없습니다.

getEnclosingConstructor()생성자 에 사용해야 합니다. (명명 된) 메소드 외부의 블록 중에는을 getEnclosingMethod()리턴합니다 null.


9
이것은 현재 실행중인 메소드를 제공하지 않습니다. 익명 / 로컬 클래스가 정의 된 메소드를 제공합니다. - docs.oracle.com/javase/6/docs/api/java/lang/...
shrini1000

7
지역 {}; 문자열 이름 = Local.class.getEnclosingMethod (). getName ();
alexsmail

21
@ shrini1000 아이디어는 정보가 필요한 곳 ​​에서이 스 니펫을 사용하고 라이브러리 루틴에 넣지 않는 것입니다.
Thorbjørn Ravn Andersen

4
팁 주셔서 감사합니다! 새 객체를 만드는 대신 this.getClass (). getEnclosingMethod (). getName ();
Lilo

3
@ 릴로가 잘못되었습니다. getEnclosingMethod클래스가 정의 된 메소드의 이름을 가져옵니다. this.getClass()전혀 도움이되지 않습니다. @wutzebaer 왜 당신이 필요합니까? 이미 액세스 할 수 있습니다.
Hazel Troost

134

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답변 ( 공개됨 )은 실제로 메소드 이름을 다시 얻기 위해 적용 할 올바른 색인을 계산합니다.


2
그것은 단지 나를 위해 "메인"이라고 말합니다. :-/
Falken 교수 교수는

@Amigable : StackTraceElement디버깅 목적으로 모든 배열 을 인쇄하고 'main'이 실제로 올바른 방법인지 확인 하려고 했 습니까?
VonC

7
JRE 6을 사용하고 잘못된 메소드 이름을 제공합니다. 내가 쓰면 작동합니다 ste[2 + depth].getMethodName(). 0은 getStackTrace()1 getMethodName(int depth), 2는 2 호출 방법입니다. @ virgo47의 답변 도 참조하십시오 .
푸르스름한

2
@ 청색 : 좋은 지적. 귀하의 의견과 virgo47의 답변에 대한 언급을 내 의견에 포함 시켰습니다.
VonC

@VonC이 구현은 정말 정확합니까? 여기서 깊이는 현재 방법을 제공하기 위해 ste.length + 1이어야합니다. 깊이 = 0을 허용한다면 ste [depth + 1]이 아니어야합니까?
mmm

85

이 코드를 사용하여 스택 추적 인덱스의 잠재적 변동성을 완화했습니다. 이제 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이 그렇게 나쁘지 않기를 바랍니다. :-)


1
이것은 여전히 ​​미묘하게 벤더에 의존합니다. JVM은이 코드에 대해 신뢰할 수있는 데이터를 제공 할 필요가 없습니다.
Thorbjørn Ravn Andersen

6
JVM 사양에 따라 JVM은 전체 스택 추적 (최적화, 인라인 등)을 제공 할 필요가 없으며 Oracle Java 5와 Oracle Java 6간에 휴리스틱이 변경되었음을 이미 발견했습니다. 코드에서 예상 한대로 작동하므로 공급 업체별 동작에 미묘하게 의존합니다. 알고있는 한 완벽하게 괜찮지 만, 예를 들어 IBM JVM (필수) 또는 Zing 인스턴스에 배치해야하는 경우 휴리스틱을 다시 방문해야 할 수도 있습니다.
Thorbjørn Ravn Andersen

1
이것은 여기에 제시된 모든 옵션 중 가장 강력한 것으로 보입니다.
Ian

46
 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

name의 값은 foo입니다.


5
Local.class.getEnclosingMethod ()가 널입니다. jdk1.6.0_31, 재생 1.2.5
eigil

@eigil 흥미롭지 만 더 많은 정보가 없다면 무엇이 잘못되었는지 또는 언제 예상해야하는지 말하기가 어렵습니다null
Maarten Bodewes

이것은 이 답변 과 동일한 요령 입니다. 그것은 가짜 객체 인스턴스를 생성하지 않는다는 장점이 있으며, 명령문에서 인라인 될 수없는 클래스 선언이 필요하다는 단점이 있습니다 (즉, 일반적으로 추가 코드 라인이 필요함).
Maarten Bodewes

@eigil 클래스 (예 : SomeClass) 또는 메소드 (예 : foo) 내에서 클래스를 정의 했습니까? 메서드 또는 생성자에 래핑되지 않고 하위 클래스를 정의하면 getEnclosingMethod ()가 null을 반환한다는 것을 알았습니다.
DN

이 답변에 설명 된대로 정확히 수행했습니다. 플레이 프레임 워크에 이상하다고 생각합니다. 아무 문제없이 '정상적인'java로 테스트되었습니다.
eigil

36

이 두 가지 옵션 모두 Java에서 작동합니다.

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

또는:

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

1
정적 메소드의 경우 : <Class> .class.getEnclosingMethod (). getName ()
jellobird

Bombe의 답변과 javadoc 표시에 따라 빈 배열을 조심하십시오. 일부 JVM이 스택 트레이스 배열을 채우지 못할 수 있습니까?
el-teedee

34

내가 찾은 가장 빠른 방법 은 다음과 같습니다.

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)에 직접 액세스합니다. 그리고 접근 가능한 메소드를 정적 변수에 저장합니다.


3
성능면에서 가장 빠릅니다. 이 주장을 뒷받침하는 마이크로 벤치 마크가 있습니까?
이브라힘 아리 에프

10
+1. 1.6에서 간단한 시간 루프를 사용하면이 방법을 사용하여 1,000,000 회 반복하는 데 1219ms new Throwable().getStackTrace()가 걸리고 사용 에는 5614ms가 걸렸습니다.
ach

1
m.setAccessible (true); AccessController.doPrivileged로 묶어야합니다. 고려해야 할 사항, 어려운 규칙은 아닙니다
avanderw

6
2016 년에 테스트되었으며 이것이 가장 빠른 속도입니다. @ach와 마찬가지로 1M 반복을 사용했습니다. 1.7_79 : 1.6 초 vs 15.2 초 1.8_74 : 1.8 초 vs 16.0 초 FWIW 벤치 마크 ste 배열의 길이 = = 23이지만이 방법은 스택 깊이에 관계없이 빠르게 유지됩니다.
Ryan

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

2
나를 위해 "getStackTrace ()에"전원이 인쇄 - 난 자바 1.5 사용하고 있습니다
잭 컴버

Bombe의 답변과 javadoc 표시에 따라 빈 배열을 조심하십시오. 일부 JVM이 스택 트레이스 배열을 채우지 못할 수 있습니까?
el-teedee

16
public static String getCurrentMethodName() {
        return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
    }

그렇습니다. 지금까지 가장 좋은 방법은 ... 메소드로 바꾸고 트레이스에서 세 번째 ([2]) 프레임 (또는 호출 된 것)을 가져옵니다.
마이크 설치류

14

이것은 virgo47의 답변 (위) 에 대한 확장입니다 .

현재 및 호출 클래스 / 메소드 이름을 가져 오기위한 정적 메소드를 제공합니다.

/* Utility class: Getting the name of the current executing method 
 * /programming/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. /programming/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
이것은 @mklemenz의 답변과 함께 스택 정보에 액세스하는 매우 빠르고 깨끗한 방법입니다.
Octavia Togami 1

12

현재 메소드를 호출 한 메소드의 이름을 얻으려면 다음을 사용할 수 있습니다.

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

이것은 내 안드로이드 폰뿐만 아니라 MacBook에서도 작동합니다.

나는 또한 시도했다 :

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

그러나 안드로이드는 "getStackTrace"를 반환합니다.

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

근데 MacBook에서 틀린 답을 얻습니다


최근에 Android에서 테스트 한 getStackTrace()[0]결과 getStackTrace()[1]. 보다 사용하는 것이 좋습니다 . YMMV.
mbm29414

안드로이드에 대한Thread.currentThread().getStackTrace()[2]
Ninja

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

SomeClass.java :

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

final StackTraceElement e = Thread.currentThread().getStackTrace()[2]; 공장; e.getClassName();전체 클래스 이름을 e.getMethodName()반환하고 methon 이름을 반환하십시오.
Marks

1
getStackTrace()[2]잘못된, 그것은이어야 getStackTrace()[3]때문에 [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3] 함수 A ()이 하나를 호출
PhilLab

11

이것은 StackWalkerJava 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();
}

StackWalker는 게 으르도록 설계되었으므로 Thread.getStackTrace전체 호출 스택에 대한 배열을 열심히 만드는 것보다 더 효율적일 수 있습니다 . 자세한 내용은 JEP를 참조하십시오.


5

대체 방법은 예외를 생성하지만 예외는 발생시키지 않고 스택 추적 데이터를 가져 오는 해당 객체를 사용하는 것입니다. 엔 클로징 방법은 일반적으로 JVM이 해당 정보를 저장하는 한 다른 방법 에서처럼 인덱스 0에 있기 때문입니다. 위에 언급했듯이. 그러나 이것이 가장 저렴한 방법은 아닙니다.

에서 Throwable.getStackTrace () (이 적어도 자바 5 이후 같은되었습니다)

배열의 0 번째 요소 (배열의 길이가 0이 아닌 것으로 가정)는 스택의 맨 위를 나타내며, 이는 시퀀스에서 마지막 메소드 호출입니다. 일반적 으로이 던지기 가능 항목을 작성하여 던지는 지점입니다.

아래 스 니펫은 클래스가 정적이 아닌 것으로 가정합니다 (getClass () 때문에).

System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());

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

1
위의 mvanle virgo47의 답변과 thorbjorn-ravn-andersen의 의견을 참조하십시오. 반복적이고 정확하지 않고 신뢰할 수없는 코드
alexsmail

@ ShivaKomuravelly 네, 그러나 어떤 상황에서도 그렇게 보이지 않으므로 나 에게서도 -1입니다.
Maarten Bodewes

3

이것을 사용하는 솔루션이 있습니다 (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())}));
    }
}

3

현재 실행중인 메소드의 이름을 얻는 의도가 무엇인지 모르겠지만, 디버깅 목적으로 만 사용되는 경우 "logback"과 같은 로깅 프레임 워크가 도움이 될 수 있습니다. 예를 들어, 로그 백에서 로깅 구성에 "% M"패턴사용 하기 만하면 됩니다. 그러나 성능이 저하 될 수 있으므로주의해서 사용해야합니다.



1

여기에 대부분의 답변이 잘못된 것 같습니다.

    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

유용한 답변에 감사드립니다.
AmerllicA

왜 대부분의 답변이 잘못된 것입니까? 많은 답변이 있으며 Java에서 모든 답변을 읽고 답변과 귀하의 답변의 차이점을 이해하는 데 정통하지 않습니다. :(
Xobotun

@mmm 죄송하지만 동의하지 않습니다. 나는 여기에 와서 많은 다른 사람들도 배우고 믿습니다. 나는 왜이 주제에 대해 더 알 가치가 없다고 생각하는지 이해할 수 없습니다. 내 코드에서 실수를 줄이고 다른화물 컬트를 따르지 말고 다른 사람들에게 경고하고 싶습니다. 최소한이 코드가 어떤 Java 버전인지 확인해야합니다. :( 아래 답변은 1.5와 1.6 사이에 스택 추적이 변경되었다고 말합니다. 향후 Java 14에 이와 비슷한 내용이 있음을 알 수 있습니다. 어떻게 알 수 있는지 또는 다른 공급 업체가있을 수 있습니다. 하나.
Xobotun

0

나는 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);
}

-2
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();

11
자세한 내용으로 편집하십시오. 검색 가능한 콘텐츠가 포함되어 있지 않으며 누군가 "이 작업을 시도해야하는 이유"를 설명하지 않기 때문에 코드 전용 및 "이것을 시도하십시오"답변은 권장되지 않습니다.
abarisone

1
이 코드는 문제를 해결하는 데 도움이 될 수 있지만 질문에 그리고 / 또는 어떻게 대답 하는지 는 설명하지 않습니다 . 이러한 추가 맥락을 제공하면 장기적인 교육 가치가 크게 향상 될 것입니다. 제발 편집 제한 및 가정이 적용되는 것을 포함하여, 설명을 추가 답변을.
Toby Speight

1
Java 7+ 전용이지만 메소드 이름을 얻는 간결한 방법입니다. 여전히, 그러한 호출의 성능 고려 사항이 남아 있습니다.
Benj

6
getEnclosingMethod()NullPointerExceptionJava 7에서 나를 위해 a 를 던졌습니다 .
Markus L

2
java.lang.Class.getEnclosingMethod ()는 기본이되는 클래스의 즉시 둘러싸는 메소드를 나타내는 Method 오브젝트를 돌려줍니다.이 Class 오브젝트가 메소드 내의 로컬 클래스 또는 익명 클래스를 나타내는 경우는 null을 리턴합니다.
스토브

-5

이 접근법의 문제점 :

class Example {
    FileOutputStream fileOutputStream;

    public Example() {
        //System.out.println("Example.Example()");

        debug("Example.Example()",false); // toggle

        try {
            fileOutputStream = new FileOutputStream("debug.txt");
        } catch (Exception exception) {
             debug(exception + Calendar.getInstance().getTime());
        }
    }

    private boolean was911AnInsideJob() {
        System.out.println("Example.was911AnInsideJob()");
        return true;
    }

    public boolean shouldGWBushBeImpeached(){
        System.out.println("Example.shouldGWBushBeImpeached()");
        return true;
    }

    public void setPunishment(int yearsInJail){
        debug("Server.setPunishment(int yearsInJail=" + yearsInJail + ")",true);
    }
}

그리고 사람들이 사용에 열중하기 전에 System.out.println(...)항상 출력을 리디렉션 할 수 있도록 몇 가지 방법을 만들어야합니다.

    private void debug (Object object) {
        debug(object,true);
    }

    private void dedub(Object object, boolean debug) {
        if (debug) {
            System.out.println(object);

            // you can also write to a file but make sure the output stream
            // ISN'T opened every time debug(Object object) is called

            fileOutputStream.write(object.toString().getBytes());
        }
    }

4
@Saksham 그것은 실제로 질문에 대답하려는 것처럼 보입니다. 위대한 시도는 아니지만 적은 시도입니다.
ivarni

@ivarni "좋은 시도"? 무슨 일이야? "키스 원리"에 익숙하십니까?
johnny

@Saksham 그것은 수사적이었습니다.
johnny

5
@johnny 코드베이스에는 271 개의 클래스가 있습니다. 클래스 당 (낮은 추정치) og 5 가지 방법으로도 1300 가지가 넘는 메소드 그리고 이것은 큰 코드베이스가 아닙니다. 접근 방식을 확장하는 데 문제가 보이지 않습니까? 나는 동의하지 않을 것에 대해 매우 기뻐하지만, 그것이 좋은 시도가 아니라고 말한 이유입니다. 사소한 코드베이스에 엄청난 양의 오버 헤드가 발생합니다.
ivarni

1
@johnny 메소드 이름이 디버깅 할 때 잘못된 방향으로 보낸 문자열과 일치하지 않는 경우가 너무 많습니다. 그러나 Java에서는 여전히 귀하의 제안이 최선이라고 생각하고 다른 대안은 너무 비쌉니다.
또 다른 메타 프로그래머
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.