在 Kotlin JVM 1.2.x 中,我可以执行以下操作:
inline fun <R> Logger.logStuff(
crossinline f: () -> R
): R {
val methodName = object {}.javaClass.enclosingMethod.name
try {
this.debug("$methodName : Begin")
f()
this.debug("$methodName : End")
} catch (ex: Exception) {
this.error("$methodName : Threw exception : $ex")
throw ex
}
}
class Foo {
fun doStuff() = log.logStuff {
1 + 3
}
}
Run Code Online (Sandbox Code Playgroud)
这会给我这样的日志:
Foo : doStuff : Begin
Foo : doStuff : End
Run Code Online (Sandbox Code Playgroud)
但是,升级到 Kotlin 1.3.50(从 1.2.x 开始)后,我收到如下日志:
Foo : logStuff : Begin
Foo : logStuff : End
Run Code Online (Sandbox Code Playgroud)
我知道currentThread().stackTrace[1].methodName
要获取封闭的方法名称,但我希望避免这种情况。
还有其他方法获取当前函数名称吗?
您可以将 logStuff() fun 转换为扩展并使您的 R 类型具体化,如下所示:
inline fun <reified R : Any> R.logStuff() {
val methodName = object {}.javaClass.enclosingMethod.name
}
Run Code Online (Sandbox Code Playgroud)
22 年 8 月 12 日更新:
这个解决方案有什么区别以及给我们带来了什么?
我们可以稍微改进一下以更好地可视化它:
inline fun <reified R : Any> R?.log(msg: String?) = this?.run {
val objectId: String = this::class.simpleName ?: this::class.hashCode().toString()
val methodName = object {}.javaClass.enclosingMethod?.name
Log.d("TAG", "$objectId.$methodName() {\n $msg\n}")
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以像这样使用它:
class ExampleClass {
fun exampleFun() {
log("test")
}
}
Run Code Online (Sandbox Code Playgroud)
它会给我们这样的输出:
ExampleClass.exampleFun() {
test
}
Run Code Online (Sandbox Code Playgroud)
由于日志函数是内联的,因此代码将在“exampleFun()”内执行。
正如您所看到的,输出中会有一个“当前函数名称”。另请注意,在某些情况下,类可能没有 simpleName,这就是为什么需要使用 hashCode。
22 年 1 月 30 日更新:
如果以上方法不适合您,请尝试以下操作:
inline fun <reified R : Any> R?.log(msg: String?) = this?.run {
val objectId: String = this::class.simpleName ?: this::class.hashCode().toString()
val methodName = StackWalker.getInstance().walk { frames ->
frames.findFirst().map { it.methodName }.orElse(null)
}
println("$objectId.$methodName() {\n $msg\n}")
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1719 次 |
最近记录: |