【问题标题】:How to correctly create a weak reference to method reference in Java如何在 Java 中正确创建对方法引用的弱引用
【发布时间】:2015-06-26 21:07:21
【问题描述】:

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

两个问题:

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

【问题讨论】:

  • 根据 WeakListChangeListener 的 JavaDoc:“注意:您必须保留对 ListChangeListener 的引用,只要它在使用中就已传入,否则很快就会被垃圾收集。”

标签: java lambda javafx weak-references


【解决方案1】:

创建方法引用(在这种情况下)就像创建任何其他对象一样。因此,如果我们将其替换为 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 中,您在 listener 字段中保留对新创建的 Foo 对象的强引用,因此只有在收集具有 listener 字段的对象时才会收集它。

Ps:如果 Java 中的方法引用确实是对方法的引用,这意味着方法本身就是一等对象(就像在 Javascript 中一样),示例 2 也可以像每个对象一样工作隐式持有对其所有方法的引用。

【讨论】:

  • 需要强调的是,即使是固定版本也取决于周围对象的可达性(具有listener 实例字段的对象)。原则上,如果它们的唯一根引用是局部变量,则优化的 JVM 可以消除整个对象图。如果“Java 中的方法引用确实是对方法的引用”,这甚至适用,并证明允许像垃圾收集这样不可预测的东西来改变程序的语义(即是否会调用事件处理程序)并不是一个好主意。 .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-26
相关资源
最近更新 更多