Kotlin 1.3.41上针对Common、JS、JVM和Native的KClass.simpleName规格为:

The simple name of the class as it was declared in the source code, or null if the class has no name (if, for example, it is an anonymous object literal).

生成null似乎很简单:获取从匿名对象文本生成的KClass的simpleName.以下代码是一个失败的try :

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
    })
}

Why is the value of name 2?

and now let's look at the bytecode for this.
this is part of the bytecode for the start function. as you can see it implements Function0 and it has an invoke method that takes a 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

   ....

and this is part of the bytecode for the anonymous object as you can see it implements 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

   .....

you can see from the bytecode that the name of your anonymous class is actually TestKt$main$2. because the compiler automatically generated a class for your file that is TestKt and another class for the main function that is TestKt$Main. then for every function or anonymous class, another class will be generated, and they are named by order. for example, here function start has a class with the name TestKt$main$1 that extends Lambda and Function0. if you add a dummy method in between in the main function like this:

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
    })
}

then the name of your class would be 3 that is the answer for why it's 2

How should I change the code to get the value of the name to be null?

you can use qualifiedName instead of simpleName. this must be a mistake in the documentation, just ignore the part in the parenthesis which says "if, for example, it is an anonymous object literal". this is what the doc says about qualifiedName:

The fully qualified dot-separated name of the class, or null if the class is local or a class of an anonymous object.

and it works as it said.

start(object: Human {
        val name = this::class.qualifiedName
        override fun think() = "Thinking really hard! Name is: $name" // name == null
    })

Kotlin相关问答推荐

为什么";";.equals(1)在柯特林语中是有效的,但";";=1是无效的?

在Jetpack Compose中创建波浪式文本动画:顺序中断问题

S使用MAP和ElseThrow的习惯用法是什么?

Kotlin-elvis算子don';不使用map.get()

为什么 Kotlin main 函数需要 @JVMStatic 注解?

Jetpack Compose - 单击 LazyColumn 的项目时应用程序崩溃

Kotlin:内部类如何访问在外部类中声明为参数的变量?

Kotlin 协程中的 Dispatchers.Main 和 Dispatchers.Default 有什么区别?

kotlin 扩展属性的惰性初始化器中的这个引用

Kotlin 具体化的泛型不会按计划保持类型

如何使用Kotlin Dokka记录主构造函数参数

ObserveForver是否了解生命周期?

大小写敏感性 Kotlin / ignoreCase

如何使用mockk库模拟android上下文

将字符串编码为Kotlin中的UTF-8

比较Kotlin的NaN

函数引用和lambdas

Android Compose 生产准备好了吗?

Kotlin 中的填充字符串

在 intelliJ 元素中集成 Kotlinx 协程