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.