현재 실행 중인 메서드의 이름을 가져오는 중
자바에서 현재 실행 중인 메서드의 이름을 얻을 수 있는 방법이 있습니까?
엄밀히 말하면 이건 통할 수 있을 거야
String name = new Object(){}.getClass().getEnclosingMethod().getName();
「」 「」 「」 등).YourClass$1.class)이 됩니다..class이 트릭을 전개하는 각 메서드에 대한 파일입니다.또한 실행 시 호출할 때마다 사용되지 않는 개체 인스턴스가 생성됩니다.따라서 이는 허용 가능한 디버깅 트릭일 수 있지만 상당한 오버헤드가 수반됩니다.
은 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.getEnclosingMethod()java.lang.reflect.Method주석 및 매개 변수 이름을 포함한 메서드의 다른 모든 정보를 검색하는 데 사용할 수 있습니다.이것에 의해, 같은 이름의 특정의 메서드를 구별할 수 있습니다(메서드 오버로드).
"에 "JavaDoc"에 .getEnclosingMethod() 안 .SecurityException내부 클래스는 동일한 클래스 로더를 사용하여 로드해야 합니다.따라서 보안 매니저가 존재하더라도 액세스 조건을 확인할 필요가 없습니다.
주의해 주십시오.를 사용하기 위해서 필요합니다.getEnclosingConstructor()컨스트럭터용입니다. 있는메서드 에서는 ( 있는) 메서드가 사용됩니다.getEnclosingMethod()null.
Thread.currentThread().getStackTrace()에는, 통상은 발신원이 되는 메서드가 포함되어 있습니다만, 함정이 있습니다(Javadoc 참조).
일부 가상 시스템은 상황에 따라 스택 추적에서 하나 이상의 스택 프레임을 생략할 수 있습니다.극단적인 경우 이 스레드와 관련된 스택 추적 정보가 없는 가상 시스템은 이 메서드에서 길이 0의 어레이를 반환할 수 있습니다.
: 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(),1getMethodName(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();
}
}
이름에는 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;
}
}
}
네이티브 메서드 getStackTraceEElement(int depth)에 직접 액세스합니다.또한 접근 가능한 메서드를 정적 변수에 저장합니다.
다음 코드를 사용합니다.
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
String methodName = e.getMethodName();
System.out.println(methodName);
이것은 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();
}
StackWalker게으르도록 설계되어 있기 때문에, 예를 들면,Thread.getStackTrace콜 스택 전체의 배열을 적극적으로 작성합니다.상세한 것에 대하여는, 「JEP」도 참조해 주세요.
public static String getCurrentMethodName() {
return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
}
이는 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 + ")";
}
}
현재 메서드를 호출한 메서드의 이름을 가져오려면 다음을 사용합니다.
new Exception("is not thrown").getStackTrace()[1].getMethodName()
안드로이드 폰뿐만 아니라 MacBook에서도 작동합니다.
저도 시도했습니다.
Thread.currentThread().getStackTrace()[1]
하지만 Android는 "getStackTrace"를 반환할 것입니다. Android의 경우 이 문제를 해결할 수 있습니다.
Thread.currentThread().getStackTrace()[2]
하지만 맥북에서 틀린 답을 얻습니다.
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
}
}
다른 방법으로는 Exception을 생성하여 스택트레이스 데이터를 취득하는 오브젝트를 사용하는 방법이 있습니다.인클로징 메서드는 일반적으로 인덱스0 이 되기 때문입니다.JVM 이 정보를 저장하는 한, 위에서 설명한 바와 같습니다.그러나 이것이 가장 저렴한 방법은 아니다.
Throwable.getStackTrace()에서 (Java 5 이후부터 동일) :
배열의 0번째 요소(배열 길이가 0이 아닌 경우)는 스택의 상단을 나타냅니다.이것은 시퀀스의 마지막 메서드 호출입니다.일반적으로 이 던질 수 있는 것이 만들어지고 던져진 시점입니다.
다음 스니펫에서는 클래스가 (getClass() 때문에) 비정적이라고 가정하고 있습니다만, 이것은 여백입니다.
System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);
이를 이용한 솔루션이 있다(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())}));
}
}
현재 실행 중인 메서드의 이름을 가져온 의도는 알 수 없지만 디버깅을 위한 것이라면 "logback"과 같은 로깅 프레임워크가 도움이 됩니다.예를 들어, 로그백에서는 로그 설정에서 "%M" 패턴을 사용하면 됩니다.단, 퍼포먼스가 저하될 수 있으므로 주의하여 사용해야 합니다.
원하는 이름이 junit 테스트 방식인 경우 junit Test Name 규칙(https://stackoverflow.com/a/1426730/3076107을 사용할 수 있습니다.
이 코드 스니펫은 최신 Android Studio와 최신 Java 업데이트를 함께 사용합니다.모든 액티비티, 프래그먼트 등에서 호출할 수 있습니다.
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)]
나는 막클멘즈의 답을 조금 다시 썼다.
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);
}
여기 대부분의 답은 틀린 것 같다.
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
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();
이 접근방식의 문제점은 무엇입니까?
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);
}
}
사람들이 리리람 and using using using using and and and and and and and and and and and and and and and and and and and and and and and and에 열광하기 전에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());
}
}
언급URL : https://stackoverflow.com/questions/442747/getting-the-name-of-the-currently-executing-method
'programing' 카테고리의 다른 글
| C# Java HashMap 등가물 (0) | 2022.07.27 |
|---|---|
| vue: 내부 컴포넌트에 커스텀 속성을 추가하여 "_ob__" 및 getter/setter를 추가하지 않도록 합니다. (0) | 2022.07.27 |
| 모바일에서만 클래스 추가 - Vuej 및 부트스트랩 (0) | 2022.07.26 |
| Vue는 v-for 루프 내의 구성 요소 앞에 하나의 구성 요소를 동적으로 추가합니다. (0) | 2022.07.26 |
| vuex 지속 상태를 사용하여 로컬 스토리지에 데이터 저장 (0) | 2022.07.26 |