我最近发现自己正在编写以下代码:
fun listener() {
// Do some stuff
adapter.removeLoadStateListener(::listener)
}
adapter.addLoadStateListener(::listener)
一位同事指出
val x1 = ::listener
val x2 = ::listener
x1 == x2 //true
x1 === x2 //false
然而,
var mySet = mutableSetOf<() -> Unit>()
fun a() { }
fun b() { }
mySet.add(::a)
mySet.add(::b)
mySet.remove(::a)
mySet.contains(::a) // false
mySet.contains(::b) // true
基于这一点,我得到的印象是我没有正确理解::MyFun
,我开始怀疑我的原始代码是否安全。
DR
::listener
引用要用作侦听器且需要多次引用的方法(例如,添加+删除)是否安全?
当您使用::listener
时,您每次都在创建一个实现接口的匿名类。但是,正如您的测试所示,匿名类的.equals
将返回它们相等,而匿名类(使用object:
语法创建)通常不是这种情况。因此,使用:Listener
创建的两个实例将与==
等价,但与===
不等价。
集合通常使用.equals
等式(==
)来确定实例是否重复,但可以创建一个由IdentityHashMap支持的集合,这样它就可以使用标识比较有效地表现为集合。这违反了设置的契约,但类可能会出于某种原因在内部使用它。
使用它是否安全取决于您使用的类是通过.equals
还是通过identity来比较侦听器实例。如果它可能使用IdentityHashMap来存储和比较侦听器,那么这是不安全的。