Как да получите име на метод, който се изпълнява?

1. Общ преглед

Понякога трябва да знаем името на текущия Java метод, който се изпълнява.

Тази бърза статия представя няколко лесни начина за получаване на името на метода в текущия стек за изпълнение.

2. Java 9: ​​API за стек-ходене

Java 9 представи API за ходене на стека, за да прехвърля JVM стековите рамки по мързелив и ефективен начин. За да намерим изпълняващия се в момента метод с този API, можем да напишем прост тест:

public void givenJava9_whenWalkingTheStack_thenFindMethod() { StackWalker walker = StackWalker.getInstance(); Optional methodName = walker.walk(frames -> frames .findFirst() .map(StackWalker.StackFrame::getMethodName)); assertTrue(methodName.isPresent()); assertEquals("givenJava9_whenWalkingTheStack_thenFindMethod", methodName.get()); }

На първо място, ние се StackWalker модел посредством getInstance () фабрика метод. След това използваме метода walk () , за да преминем рамките на стека отгоре надолу:

  • Методът walk () може да преобразува поток от рамки на стека - Stream - към каквото и да било
  • Първият елемент в дадения поток е горната рамка на стека
  • Горната рамка на стека винаги представлява текущо изпълняващия се метод

Следователно, ако получим първия елемент от потока, ще знаем подробностите за изпълнявания в момента метод. По-конкретно, можем да използваме StackFrame.getMethodName (), за да намерим името на метода.

2.1. Предимства

В сравнение с други подходи (повече за тях по-късно), API на Stack-Walking има няколко предимства:

  • Няма нужда да създавате фиктивен анонимен екземпляр на вътрешен клас - нов обект (). GetClass () {}
  • Няма нужда да създавате фиктивно изключение - нов Throwable ()
  • Не е необходимо с нетърпение да заснемете целия стек, което може да струва скъпо

Напротив, StackWalker разхожда стека един по един мързеливо. В този случай той извлича само горната рамка, за разлика от подхода на стека, който с нетърпение улавя всички кадри.

Изводът е, използвайте API-то на Stack-Walking, ако сте на Java 9+.

3. Използване на getEnclosingMethod

Можем да намерим името на метода, който се изпълнява, като използваме API на getEnclosingMethod () :

public void givenObject_whenGetEnclosingMethod_thenFindMethod() { String methodName = new Object() {} .getClass() .getEnclosingMethod() .getName(); assertEquals("givenObject_whenGetEnclosingMethod_thenFindMethod", methodName); }

4. Използване на трасируема стека

Използването на проследяване на стека на Throwable ни дава проследяване на стека с метода, който се изпълнява в момента:

public void givenThrowable_whenGetStacktrace_thenFindMethod() { StackTraceElement[] stackTrace = new Throwable().getStackTrace(); assertEquals( "givenThrowable_whenGetStacktrace_thenFindMethod", stackTrace[0].getMethodName()); }

5. Използване на проследяване на стека на нишки

Също така проследяването на стека на текуща нишка (от JDK 1.5) обикновено включва името на метода, който се изпълнява:

public void givenCurrentThread_whenGetStackTrace_thenFindMethod() { StackTraceElement[] stackTrace = Thread.currentThread() .getStackTrace(); assertEquals( "givenCurrentThread_whenGetStackTrace_thenFindMethod", stackTrace[1].getMethodName()); }

Трябва обаче да помним, че това решение има един съществен недостатък. Някои виртуални машини могат да пропуснат една или повече рамки на стека. Въпреки че това не е често срещано, трябва да сме наясно, че това може да се случи.

6. Заключение

В този урок представихме няколко примера за това как да получите името на текущо изпълнения метод. Примерите се основават на следи от стека и getEnclosingMethod () .

Както винаги, можете да разгледате примерите, предоставени в тази статия, в GitHub. Също така, примери за Java 9 са налични в нашия модул Java 9 GitHub.