我稍微修改了你的代码:
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
})