在Kotlin 1.3.41上KClass.simpleName
的Common,JS,JVM和Native规范是:
在源代码中声明的类的简单名称,或者 如果该类没有名称,则返回null(例如,如果它是一个匿名名称) 对象文字)。
生成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
?
答案 0 :(得分:1)
我对您的代码做了一些更改:
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
})
}
为什么名称2的值是
现在让我们看看它的字节码。
这是start
函数的字节码的一部分。如您所见,它实现了Function0
,并且它具有一个invoke
的{{1}}方法。
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
})
}
那就是为什么它是2的答案
我应该如何更改代码以使名称的值为空?
您可以使用3
代替qualifiedName
。这一定是文档中的错误,只需忽略括号中的部分,例如“如果它是一个匿名对象文字”。
这就是医生对qualifiedName的评价:
该类的全限定点名,如果该类是本地或匿名对象的类,则为null。
它像它所说的那样工作。
simpleName
答案 1 :(得分:0)
从Kotlin中的simpleName中获取null的唯一方法是引用Java构建的类,或者使用类定义从字面上覆盖simpleName。默认情况下,Kotlin在JVM上生成的类始终具有定义的simpleName属性。