Kotlin 1.3.x中匿名对象的Kotlin当前函数名不再有效

fiei3ece  于 2022-12-13  发布在  Kotlin
关注(0)|答案(1)|浏览(117)

在KotlinJVM 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
    }
}

这将给予如下日志:

Foo : doStuff : Begin
Foo : doStuff : End

但是,在升级到Kotlin1.3.50(从1.2.x)之后,我得到了如下日志:

Foo : logStuff : Begin
Foo : logStuff : End

我知道使用currentThread().stackTrace[1].methodName来获取封闭方法名,但我希望避免这样做。
是否有其他方法可以获取当前函数名?

sirbozc5

sirbozc51#

你可以把你的logStuff()fun转换成extension,使你的R类型具体化,如下所示:

inline fun <reified R : Any> R.logStuff() {
    val methodName = object {}.javaClass.enclosingMethod.name
}

2022年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}")
}

现在我们可以这样使用它:

class ExampleClass {
    fun exampleFun() {
        log("test")
    }
}

它将给予如下输出:

ExampleClass.exampleFun() {
  test
}

因为log函数是内联的,所以代码将在“exampleFun()"中执行。
正如你所看到的,在输出中会有一个“当前函数名”。请注意,在某些情况下类可能没有simpleName,这就是为什么有一个回退到hashCode。

相关问题