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

时间:2015-06-26 21:07:22

标签: java lambda javafx weak-references

我想将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));
}

两个问题:

  • 当创建方法引用的弱引用时,究竟会发生什么?
  • (2)和(3)之间有什么区别?

1 个答案:

答案 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));
}

现在差异变得相当明显:

  1. 在示例2中,新创建的Foo实例立即有资格进行垃圾回收,因为没有任何强有力的参考。
  2. 在示例3中,您对Foo字段中新创建的listener对象保持强烈引用,因此仅在收集具有listener字段的对象时才会收集该对象。
  3. Ps:如果Java中的方法引用确实是对方法的引用,意味着方法本身就是第一类对象(比如在Javascript中),示例2也会起作用,因为每个对象都会隐含地提及他们所有的方法。