两个可观察量指向相同的参考

pis*_*ffe 2 java android kotlin

我编写了以下示例并检查了对象a和b的observerA变量的值.

class Test {
    val observerA = Observer<String>{}
}
Run Code Online (Sandbox Code Playgroud)

校验

val a = Test()
val b = Test()
AppLogger.LOGE("[A]ObserverA: ${a.observerA} [B]ObserverA: ${b.observerA}")
Run Code Online (Sandbox Code Playgroud)

结果

[A]ObserverA: com.test.Test$observerA$1@e3d8a1b  
[B]ObserverA: com.test.Test$observerA$1@e3d8a1b
Run Code Online (Sandbox Code Playgroud)

我的猜测是a.observerA和a.observerA应该是不同的,但它们引用相同的对象.

当我在下面编写observerA时,我看到创建了不同的对象.我不知道为什么会出现这种差异.

val observerA = object : Observer<String>{
    override fun onChanged(t: String?) {

    }
}
Run Code Online (Sandbox Code Playgroud)

zsm*_*b13 6

当您使用此语法时,您将使用空主体定义lambda:

Observer<String>{}
Run Code Online (Sandbox Code Playgroud)

这个lambda将被编译成一个匿名类.如果lambda没有捕获任何变量,作为优化步骤,它只会有一个实例(因为你无论如何都无法区分行为).

正如您已经发现的那样,您可以强制编译器Observer使用完整的对象表达式语法创建新的实例,这样可以保证每次都有一个新实例.


上述陈述的来源,来自Kotlin in Action书:

从Kotlin 1.0开始,每个lambda表达式都被编译成一个匿名类(...).如果lambda捕获变量,则匿名类将为每个捕获的变量创建一个字段,并为每个调用创建该类的新实例.否则,将创建单个实例.通过在声明lambda(...)的函数名称中添加后缀来派生类的名称.