Kotlin 1.3.41 上针对 Common、JS、JVM 和 Native 的 KClass.simpleName
的规范是:
生成 null 似乎很简单:获取从匿名对象文字生成的 KClass 的 simpleName。下面的代码是一个失败的尝试:
interface Human { fun think(): String }
@Test fun `when finding the name of an anonymous object verify the name is null`() {
fun start(man: Human) = println(man.think())
start(object: Human {
val name = this::class.simpleName
override fun think() = "Thinking really hard! Name is: $name" // name == 2
})
}
我的期望是名称应该是
null
。为什么名称为 2 的值?我应该如何更改代码以使 name 的值为 null
? 最佳答案
我稍微改变了你的代码:
interface Human { fun think(): String }
fun main() {
fun start(man: Human) = println(man.think())
start(object: Human {
val name = this::class.java.simpleName
override fun think() = "Thinking really hard! Name is: $name" // name == 2
})
}
现在让我们看看这个字节码。
这是
start
函数的字节码的一部分。如您所见,它实现了 Function0
并且它有一个 invoke
方法,它采用 Human
。final class com/example/customview/TestKt$main$1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function1 {
// access flags 0x1041
public synthetic bridge invoke(Ljava/lang/Object;)Ljava/lang/Object;
ALOAD 0
ALOAD 1
CHECKCAST com/example/customview/Human
INVOKEVIRTUAL com/example/customview/TestKt$main$1.invoke (Lcom/example/customview/Human;)V
GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
ARETURN
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x11
public final invoke(Lcom/example/customview/Human;)V
....
这是匿名对象字节码的一部分,你可以看到它实现了 Human
:public final class com/example/customview/TestKt$main$2 implements com/example/customview/Human {
OUTERCLASS com/example/customview/TestKt main ()V
// access flags 0x12
private final Ljava/lang/String; name
.....
您可以从字节码中看到您的匿名类的名称实际上是 TestKt$main$2
。因为编译器会自动为您的文件生成一个类 TestKt
和另一个主函数类 TestKt$Main
。然后对于每个函数或匿名类,将生成另一个类,并按顺序命名它们。例如,这里的函数 start
有一个名为 TestKt$main$1
的类,它扩展了 Lambda
和 Function0
。如果您在主函数中添加一个虚拟方法,如下所示:
fun main() {
fun start(man: Human) = println(man.think())
fun nothing() = {}
start(object: Human {
val name = this::class.java.simpleName
override fun think() = "Thinking really hard! Name is: $name" // name == 3 this time
})
}
那么你的类(class)名称将是 3
这就是为什么它是 2 的答案您可以使用
qualifiedName
而不是 simpleName
。这一定是文档中的错误,只需忽略括号中的部分,即“例如,如果它是匿名对象文字”。这是文档中关于qualifiedName 的说明:
它像它所说的那样工作。
start(object: Human {
val name = this::class.qualifiedName
override fun think() = "Thinking really hard! Name is: $name" // name == null
})
关于kotlin - 如何使用 Kotlin KClass 属性 simpleName 生成空值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57229715/