我想将JavaFX ListChangeListener
注册到ObservableList
。但是我注意到,在某些情况下,监听器没有被调用。
(1)如果监听器是方法参考,那么一切正常:
// using a direct method reference:
private final ListChangeListener<String> listener = this::listDidChange;
/* ... */
public void init() {
list.addListener(listener);
}
(2)但是,如果Listener是同一方法的弱引用,则不会调用侦听器:
// 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));
}
两个问题:
答案 0 :(得分:8)
创建方法引用(在本例中)就像创建任何其他对象一样。因此,如果我们用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));
}
现在差异变得相当明显:
Foo
实例立即有资格进行垃圾回收,因为没有任何强有力的参考。Foo
字段中新创建的listener
对象保持强烈引用,因此仅在收集具有listener
字段的对象时才会收集该对象。 Ps:如果Java中的方法引用确实是对方法的引用,意味着方法本身就是第一类对象(比如在Javascript中),示例2也会起作用,因为每个对象都会隐含地提及他们所有的方法。