我想添加到属性侦听器,等待调用此侦听器并删除此侦听器。所以我写了下面的代码:
ChangeListener<String> listener = (observable, oldValue, newValue) -> {
textField.setStyle("-fx-border-color:black");
textField.textProperty().removeListener(listener); //LINE X
};
textField.textProperty().addListener(listener);
然而,在LINE X,我得到Variable listener might not have been initialized
。如何在ChangeListener中引用属性ChangeListener以将其删除?
答案 0 :(得分:3)
来自JLS,section 15.27.2:
与匿名类声明中出现的代码不同,名称的含义以及出现在lambda主体中的this和super关键字以及引用声明的可访问性与周围上下文中的相同(除了lambda参数引入新的名)。
...
实际上,lambda表达式需要谈论自己(要么递归地调用自身还是调用其他方法)是不寻常的,而更常见的是想要使用名称来引用封闭中的内容。否则将被遮蔽的类(this,toString())。 如果lambda表达式需要引用自身(就好像通过它),则应该使用方法引用或匿名内部类。
(我的重点。)
因此,简而言之,lambda表达式无法引用自身。您需要将其重构为匿名内部类:
ChangeListener<String> listener = new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
textField.setStyle("-fx-border-color:black");
textField.textProperty().removeListener(this);
}
};
textField.textProperty().addListener(listener);
当然,此时您可能不再需要参考:
textField.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
textField.setStyle("-fx-border-color:black");
textField.textProperty().removeListener(this);
}
});