1. 概述
本文将介绍几种在 Kotlin 中获取当前执行函数名称的方法。
如果你使用的是 Java 9 及以上版本,第一种方法是最推荐的。除此之外,我们还会介绍一些“非主流”方式,虽然它们确实能工作,但往往伴随着一些性能或兼容性上的问题,属于“踩坑级”方案。
2. 使用 Stack-Walking API
Java 9 引入了 Stack-Walking API,用于惰性遍历当前线程的调用栈帧。相比传统方式,该 API 更加高效,因为它不会一次性捕获所有栈帧,也不会创建多余的中间对象。
每个栈帧代表一次方法调用,栈顶帧即为当前正在执行的方法。我们可以从中提取方法名:
fun functionNameWithStackWalker(): String? {
return StackWalker.getInstance().walk { frames ->
frames.findFirst().map { it.methodName }.orElse(null)
}
}
walk()
方法接收一个函数式接口,参数是 StackFrame
的流。我们只需获取第一个栈帧,因此调用 findFirst()
,并通过 methodName
获取当前函数名。
✅ 示例验证:
val name = functionNameWithStackWalker()
assertEquals("functionNameWithStackWalker", name)
⚠️ 注意:该方法仅适用于 Java 9 及以上版本。
3. 使用匿名内部类
通过在函数内部定义一个匿名内部类,我们可以借助 Java 的 Class
API 获取其外围方法名:
fun functionNameWithAnonymousInnerClass(): String {
return object {}.javaClass.enclosingMethod.name
}
在 Java 中等价写法为:
new Object() {};
Kotlin 中的 object {}
会在编译时生成一个匿名类,我们通过 enclosingMethod.name
获取其定义所在的函数名。
✅ 示例验证:
val name = functionNameWithAnonymousInnerClass()
assertEquals("functionNameWithAnonymousInnerClass", name)
❌ 缺点:这种方式会创建一个无意义的临时对象,效率较低,仅建议在 JVM 版本低于 Java 9 时使用。
4. 捕获堆栈跟踪信息
Thread.currentThread().getStackTrace()
返回当前线程的堆栈跟踪信息。我们可以通过它来获取当前执行的方法名:
fun functionNameWithStackTraces(): String {
return Thread.currentThread().stackTrace[1].methodName
}
⚠️ 注意:getStackTrace()
返回的数组中,第 0 项是 getStackTrace()
本身,第 1 项才是调用它的函数。
❌ 缺点:该方法会一次性捕获整个堆栈,性能较差,不建议频繁使用。
5. 总结
我们介绍了三种主要方式来获取当前执行函数的名称:
方法 | 适用版本 | 效率 | 推荐程度 |
---|---|---|---|
Stack-Walking API | Java 9+ | ✅ 高 | ✅ 强烈推荐 |
匿名内部类 | Java 6+ | ❌ 低 | ⚠️ 用于兼容旧版本 |
堆栈跟踪 | Java 1+ | ❌ 最低 | ❌ 不推荐 |
如无特殊兼容性要求,推荐优先使用 Stack-Walking API。
所有完整代码示例可在 GitHub 仓库 中找到。