提问者:小点点

使用函数引用注册和取消注册侦听器是否安全?


我最近发现自己正在编写以下代码:

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

  1. 使用::listener引用要用作侦听器且需要多次引用的方法(例如,添加+删除)是否安全?
  2. 关于匿名类等的幕后实际发生了什么?

共1个答案

匿名用户

当您使用::listener时,您每次都在创建一个实现接口的匿名类。但是,正如您的测试所示,匿名类的.equals将返回它们相等,而匿名类(使用object:语法创建)通常不是这种情况。因此,使用:Listener创建的两个实例将与==等价,但与===不等价。

集合通常使用.equals等式(==)来确定实例是否重复,但可以创建一个由IdentityHashMap支持的集合,这样它就可以使用标识比较有效地表现为集合。这违反了设置的契约,但类可能会出于某种原因在内部使用它。

使用它是否安全取决于您使用的类是通过.equals还是通过identity来比较侦听器实例。如果它可能使用IdentityHashMap来存储和比较侦听器,那么这是不安全的。