如何在 Java 中正确创建对方法引用的弱引用

How to correctly create a weak reference to method reference in Java

我想将 JavaFX ListChangeListener 注册到 ObservableList。但是我注意到,在某些情况下,不会调用 Listener。

(1) 如果 Listener 是方法引用,一切正常:

// using a direct method reference:
private final ListChangeListener<String> listener = this::listDidChange;

/* ... */
public void init() {
    list.addListener(listener);
}

(2) 但是,如果监听器是同一方法的弱引用,则不会调用监听器:

// using a weak method reference:
private final ListChangeListener<String> listener = new WeakListChangeListener<String>(this::listDidChange);

/* ... */
public void init() {
    list.addListener(listener);
}

(3) 现在真正有趣的是,它又开始工作了,尽管它应该和前面的例子一样:

// direct method reference wrapped into a weak ref later:
private final ListChangeListener<String> listener = this::listDidChange;

/* ... */
public void init() {
    list.addListener(new WeakListChangeListener<String>(listener));
}

两个问题:

创建方法引用(在本例中)就像创建任何其他方法引用一样 object。因此,如果我们将其替换为 new 表达式,示例 2 将变为:

private final ListChangeListener<String> listener = new WeakListChangeListener<String>(new Foo());

public void init() {
    list.addListener(listener);
}

而示例 3 将是:

// direct method reference wrapped into a weak ref later:
private final ListChangeListener<String> listener = new Foo();

public void init() {
    list.addListener(new WeakListChangeListener<String>(listener));
}

现在区别变得相当明显:

  1. 在示例 2 中,新创建的 Foo 实例立即符合垃圾 collection 的条件,因为没有任何东西对它具有强引用。
  2. 在示例 3 中,您在 listener 字段中保留对新创建的 Foo object 的强引用,因此只有当 object 具有listener 字段已收集。

P.s.: 如果 Java 中的方法引用真的是对方法的引用,意味着方法是 first-class objects 在他们自己的权利(就像在 Javascript 中),示例 2 也可以工作,因为每个 object 都会隐式地持有对他们所有方法的引用。