为什么ChangeListener <t>的行为因T参数而异

时间:2016-01-14 15:56:20

标签: java-8 javafx-8

考虑以下计划:

import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;

/**
 *
 * @author kachna
 */
public class ListPropertyTest {

    public static void main(String[] args) {
        StringProperty p = new SimpleStringProperty();
        p.addListener((obs, old, nw) -> {
            System.out.println("String Property; oldString: " + old + ", newString: " + nw);
        });
        p.set("1");

        ListProperty<String> listProperty = new SimpleListProperty<>(FXCollections.observableArrayList());
        listProperty.addListener((obs, old, nw) -> {
            System.out.println("ListProperty; oldList:  " + old + ", newList: " + nw);

        });

        listProperty.addAll("1", "2", "3");

    }
}

运行程序会得到以下输出:

String Property; oldString: null, newString: 1
ListProperty; oldList:  [1, 2, 3], newList: [1, 2, 3]

正如您所看到的,旧值是:

    nullT 时,
  1. String
  2. T为时,该值等于新值 ObservableList<String>

1 个答案:

答案 0 :(得分:3)

这是一个错误:当包装列表的内容发生变化时,ListProperty根本不应该触发更改的事件:它应该只触发列表更改的事件。换句话说,您应该只能从

中检测到更改
listProperty.addAll("1", "2", "3");

与听众

listProperty.addListener((ListChangeListener<? extends String> change) -> {
    // e.g.
    while (change.next()) {
        if (change.wasAdded()) {
            System.out.println(change.getAddedSubList());
        }
    }
});

您注册的听众只应在您更改实际参考时触发,例如:与

listProperty.setValue(FXCollections.observableArrayList("1","2","3"));

这可能是一个无法在不破坏现有代码的情况下修复的错误:我不知道是否有计划纠正此问题。

实际发生的是更改事件被触发,但旧值和新值引用相同的列表(因为实际的包装列表引用没有被更改)。因此,无论您是从toString()还是old调用它,nw方法都返回相同的值,并提供列表的当前内容。