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


답변:


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.