JavaFX属性用方法引用添加的监听器无法移除,是预期行为还是Bug?
方法引用添加ChangeListener后无法移除的原因及解决办法
这不是Bug,是JavaFX的预期行为。
你遇到的问题核心在于:每次使用App::test这种方法引用时,都会生成一个全新的ChangeListener实例。你调用addListener(App::test)时创建了实例A并注册到属性上,调用removeListener(App::test)时又生成了一个完全不同的实例B——因为这两个方法引用是独立的调用,JVM不会为它们复用同一个对象。所以移除操作其实是在尝试删除一个根本没注册过的实例B,原来的实例A依然绑定在属性上,当你调用b.set(false)时自然还会触发监听器,导致两次打印。
你可以用一段简单的代码验证这个结论:
ChangeListener<Object> listener1 = App::test; ChangeListener<Object> listener2 = App::test; System.out.println(listener1 == listener2); // 输出false,说明是两个不同对象
解决方法很简单:把方法引用生成的监听器实例提前保存到变量中,添加和移除操作都使用这个变量即可:
public class App { public static void main(String[] args) { BooleanProperty b = new SimpleBooleanProperty(false); // 提前保存监听器实例 ChangeListener<Object> listener = App::test; b.addListener(listener); b.set(true); b.removeListener(listener); b.set(false); // 此时不会触发监听器,只会打印一次"Hello World!" } static void test(Object b, Object o, Object n) { System.out.println("Hello World!"); } }
内容的提问来源于stack exchange,提问作者Josephus87
相关产品推荐
相关产品推荐

