Добавить в корзинуПозвонить
Найти в Дзене
Умный пульс

Получить имя текущей выполняемой функции в Kotlin

В этом руководстве мы познакомимся с несколькими способами получения имени текущей выполняемой функции в Kotlin. Первый способ является наиболее идиоматичным, если мы используем Java 9. Помимо него, мы также рассмотрим несколько «хакерских» подходов, которые работают, но имеют свои недостатки.
Java 9 представила API Stack-Walking — для ленивого обхода кадров стека текущего потока. Этот API обеспечивает более эффективный обход, так как не захватывает все кадры сразу (что ресурсоёмко) и не создает лишние объекты или классы, в отличие от альтернативных решений. Верхний кадр стека представляет последнюю вызванную функцию. Мы можем использовать этот API, чтобы получить имя функции из верхнего кадра: fun functionNameWithStackWalker(): String? {
return StackWalker.getInstance().walk { frames ->
frames.findFirst().map { it.methodName }.orElse(null)
}
} Метод walk() принимает функцию, которой передаётся поток StackFrame-ов. Таким образом, мы можем лениво обходить стек кадр за к
Оглавление

1. Обзор

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

Первый способ является наиболее идиоматичным, если мы используем Java 9. Помимо него, мы также рассмотрим несколько «хакерских» подходов, которые работают, но имеют свои недостатки.

2. API Stack-Walking


Java 9 представила API Stack-Walking — для ленивого обхода кадров стека текущего потока. Этот API обеспечивает более эффективный обход, так как не захватывает все кадры сразу (что ресурсоёмко) и не создает лишние объекты или классы, в отличие от альтернативных решений.

Верхний кадр стека представляет последнюю вызванную функцию. Мы можем использовать этот API, чтобы получить имя функции из верхнего кадра:

fun functionNameWithStackWalker(): String? {
return StackWalker.getInstance().walk { frames ->
frames.findFirst().map { it.methodName }.orElse(null)
}
}

Метод walk() принимает функцию, которой передаётся поток StackFrame-ов. Таким образом, мы можем лениво обходить стек кадр за кадром и извлекать нужную информацию.

В приведённой функции мы получаем только верхний кадр с помощью findFirst(). Объект StackFrame содержит информацию об этом кадре, и мы используем его свойство methodName (или getMethodName() в Java), чтобы узнать имя текущей функции.

Проверим работу:

val name = functionNameWithStackWalker()
assertEquals("functionNameWithStackWalker", name)

3. Анонимный внутренний класс


Мы можем определить анонимный внутренний класс внутри функции. Поскольку API Class в Java позволяет получить информацию о внешнем методе, мы также можем получить имя текущей функции:

fun functionNameWithAnonymousInnerClass(): String {
return object {}.javaClass.enclosingMethod.name
}

Эквивалент в Java:

new Object() {};

Таким образом, определив анонимный внутренний класс в функции, мы можем получить имя окружающего метода через enclosingMethod (getEnclosingMethod() в Java):

val name = functionNameWithAnonymousInnerClass()
assertEquals("functionNameWithAnonymousInnerClass", name)

Этот способ менее эффективен и менее идиоматичен, так как создаёт ненужный объект. Использовать его стоит только в том случае, если вы работаете с JVM до версии 9.

4. Захват трассировки стека


Метод getStackTrace() у класса Thread возвращает массив объектов StackTraceElement, представляющих стек вызовов потока. Мы можем использовать его вместе с Thread.currentThread():

fun functionNameWithStackTraces(): String {
return Thread.currentThread().stackTrace[1].methodName
}

Так как getStackTrace() будет самой верхней функцией в стеке, второй элемент массива будет указывать на вызывающую функцию.

Однако getStackTrace() захватывает весь стек сразу, что делает этот метод самым неэффективным. Поэтому использовать его стоит только в крайнем случае.

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


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

Оригинал статьи: https://www.baeldung.com/kotlin/name-of-currently-executing-function