Java получить имя вызывающего метода

Получение имени текущего выполняемого метода

Есть ли способ получить имя выполняющегося в настоящее время метода в Java?

23 ответа

Thread , currentThread() , getStackTrace() обычно содержит метод, из которого вы его вызываете, но есть подводные камни (см. Javadoc):

Некоторые виртуальные машины могут при некоторых обстоятельствах пропускать один или несколько стековых фреймов из трассировки стека. В крайнем случае виртуальной машине, у которой нет информации трассировки стека относительно этого потока, разрешено возвращать массив нулевой длины из этого метода.

Технически это будет работать.

String name = new Object()<>.getClass().getEnclosingMethod().getName(); 

Тем не менее, новый анонимный внутренний класс будет создан во время компиляции (например, YourClass$1.class ). Так что это создаст .class файл для каждого метода, который использует этот трюк. Кроме того, экземпляр неиспользуемого объекта создается при каждом вызове во время выполнения. Так что это может быть приемлемой уловкой отладки, но она сопряжена со значительными накладными расходами.

Преимущество этого трюка в том, что getEncosingMethod() возвращается java.lang.reflect.Method которая может использоваться для получения всей другой информации о методе, включая аннотации и имена параметров. Это позволяет различать конкретные методы с одинаковыми именами (перегрузка метода).

Обратите внимание, что в соответствии с JavaDoc getEnclosingMethod() этот трюк не должен бросать SecurityException поскольку внутренние классы должны загружаться с использованием того же загрузчика классов. Поэтому нет необходимости проверять условия доступа, даже если присутствует менеджер безопасности.

Читайте также:  Using html code in wordpress

Требуется использовать getEnclosingConstructor() для конструкторов. Во время блоков вне (именованных) методов, getEnclosingMethod() возвращается null ,

Январь 2009 г.:
Полный код будет (для использования с учетом предостережения @Bombe):

/** * Get the method name for a depth in call stack. 
* 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 года:

  • 0 является getStackTrace() ,
  • 1 является getMethodName(int depth) а также
  • 2 вызывает метод.

Ответ virgo47 (upvoted) на самом деле вычисляет правильный индекс для применения, чтобы вернуть имя метода.

Мы использовали этот код для смягчения потенциальной изменчивости в индексе трассировки стека — теперь просто вызовите 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 a-info"> 
92
Источник Поделиться
2011-12-21 16:13

Оба эти варианта работают для меня с Java:

new Object()<>.getClass().getEnclosingMethod().getName() 
Thread.currentThread().getStackTrace()[1].getMethodName() 
 public class SomeClass < public void foo()< class Local <>; String name = Local.class.getEnclosingMethod().getName(); > > 

имя будет иметь значение foo.

Это можно сделать с помощью StackWalker начиная с 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 для получения дополнительной информации.

Самый быстрый способ, который я нашел, заключается в том, что:

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 глубине). И сохраняет доступный Метод в статической переменной.

Используйте следующий код:

 StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace(); StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st String methodName = e.getMethodName(); System.out.println(methodName); 
public static String getCurrentMethodName()

Он предоставляет несколько статических методов для получения текущих и вызывающих имен классов / методов.

/* Utility class: Getting the name of the current executing method * https://stackru.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 stackru posts eg. https://stackru.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.stackru.util; public class StackTraceInfo < /* (Lifted from virgo47's stackru 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, а также на моем телефоне Android

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

но Android вернет "getStackTrace", я мог бы исправить это для Android с

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

но тогда я получаю неправильный ответ на моем MacBook

Источник

Получение имени текущего выполняемого метода в Java

Ситуации, когда необходимо получить имя текущего выполняемого метода, могут встретиться довольно часто. Например, при отладке программы или при логировании.

Ситуации, когда необходимо получить имя текущего выполняемого метода, могут встретиться довольно часто. Например, при отладке программы или при логировании. Приведем пример: есть метод, в котором происходит некоторое действие, и результат этого действия записывается в лог. В логе необходимо указать, в каком именно методе было выполнено это действие.

В таком случае возникает вопрос: как получить имя текущего метода в Java? Для этого существует несколько способов.

Способ 1. Использование StackTrace

Java предоставляет возможность получить стек вызовов для текущего потока с помощью метода Thread.currentThread().getStackTrace() . Этот метод возвращает массив StackTraceElement , каждый из которых представляет собой элемент стека вызовов. Нулевой элемент массива ( [0] ) — это сам метод getStackTrace , первый элемент ( [1] ) — это метод, который вызвал getStackTrace , и так далее. Таким образом, чтобы получить имя текущего метода, нужно обратиться к второму элементу этого массива.

String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();

Способ 2. Использование исключений

Другой способ получить стек вызовов — использовать исключения. Метод Throwable.getStackTrace() также возвращает массив StackTraceElement , аналогичный тому, который возвращает Thread.currentThread().getStackTrace() . Однако в этом случае нулевой элемент массива ( [0] ) — это метод, где было создано исключение.

String methodName = new Exception().getStackTrace()[0].getMethodName();

Оба этих способа позволяют получить имя текущего выполняемого метода. Однако стоит помнить, что оба способа имеют относительно высокую стоимость в плане производительности, поэтому их стоит использовать с умом и не злоупотреблять.

Источник

Как получить имя выполняемого метода?

Иногда нам нужно знать имя текущего выполняемого метода Java.

В этой краткой статье представлено несколько простых способов получения имени метода в текущем стеке выполнения.

2. Java 9: API для работы со стеком

Java 9 представила API для обхода стека для ленивого и эффективного обхода кадров стека JVM. Чтобы найти выполняемый в данный момент метод с помощью этого API, мы можем написать простой тест:

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

Во-первых, мы получаем экземпляр StackWalker |, используя getInstance () |/заводской метод. Затем мы используем метод walk() для перемещения кадров стека сверху вниз:

  • Метод walk() может преобразовать поток стековых кадров — Поток Стековый кадр> — во что угодно
  • Первым элементом в данном потоке является верхний кадр в стеке
  • Верхний кадр в стеке всегда представляет текущий выполняемый метод

Поэтому, если мы получим первый элемент из потока, мы будем знать детали текущего метода выполнения. Более конкретно, мы можем использовать Stack Frame.GetMethod() для поиска имени метода.

2.1. Преимущества

По сравнению с другими подходами (подробнее о них позже) API для обхода стека имеет несколько преимуществ:

  • Нет необходимости создавать фиктивный анонимный экземпляр внутреннего класса — новый объект().getClass() <>
  • Нет необходимости создавать фиктивное исключение — new Throwable()
  • Нет необходимости охотно захватывать весь маршрут стека, что может быть дорогостоящим

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

Суть в том, что используйте API для обхода стека, если вы используете Java 9+.

3. Использование метода Getenclosing

Мы можем найти имя выполняемого метода с помощью getEnclosingMethod() API:

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

4. Использование Трассировки сбрасываемого Стека

Использование Выбрасываемая трассировка стека дает нам трассировку стека с выполняемым в данный момент методом:

public void givenThrowable_whenGetStacktrace_thenFindMethod()

5. Использование Трассировки Стека потоков

Кроме того, трассировка стека текущего потока (начиная с JDK 1.5) обычно включает имя выполняемого метода:

public void givenCurrentThread_whenGetStackTrace_thenFindMethod()

Однако мы должны помнить, что у этого решения есть один существенный недостаток. Некоторые виртуальные машины могут пропускать один или несколько кадров стека. Хотя это не часто встречается, мы должны знать, что это может произойти.

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

В этом уроке мы представили несколько примеров того, как получить

В этом уроке мы представили несколько примеров того, как получить

Источник

Как получить имя исполняемого метода?

Иногда нам нужно знать имя текущего выполняемого метода Java.

В этой быстрой статье представлены несколько простых способов получить имя метода в текущем стеке выполнения.

2. ИспользуяgetEnclosingMethod

Мы можем найти имя выполняемого метода с помощью APIgetEnclosingMethod():

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

3. Использование трассировки стекаThrowable

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

public void givenThrowable_whenGetStacktrace_thenFindMethod()

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

Кроме того, трассировка стека текущего потока (начиная с JDK 1.5) обычно включает имя выполняемого метода:

public void givenCurrentThread_whenGetStackTrace_thenFindMethod()

Однако нужно помнить, что у этого решения есть один существенный недостаток. Некоторые виртуальные машины могут пропускать один или несколько кадров стека. Хотя это не часто, мы должны знать, что это может случиться.

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

В этом уроке мы представили несколько примеров того, как получить имя выполняемого в данный момент метода. Примеры основаны на трассировках стека иgetEnclosingMethod().

Как всегда, вы можете ознакомиться с примерами из этой статьиover on GitHub.

Источник

Оцените статью