我正在自己研究Oracle的JavaFX教程。在做Swing多年(很久以前)之后,我对新的智能功能着迷,包括。特性。我很惊讶地看到这些示例(例如https://docs.oracle.com/javafx/2/ui_controls/table-view.htm)没有以我认为“正确”的方式使用它们。
该示例创建一个带有属性作为字段的Person
类:
public static class Person {
private final SimpleStringProperty firstName;
...
但是, setter/getter 不是针对属性,而是针对其值
public String getFirstName() {
return firstName.get();
}
因此,当将它们绑定(bind)到列中的
TableCell
时,它将它们包装在新属性中: emailCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("firstName"));
这在我看来是令人费解的,并且错过了事件传播的真正优势,因为它并非简单地使用以下方法:
firstNameCol.setCellValueFactory( celldata ->
celldata.getValue().firstNameProperty());
我的问题:这个示例为什么没有直接在控件中公开和使用bean的属性,这是有原因的吗?我在这里想念什么吗?
注意:我确实以这种方式更改了代码,该示例的效果更好:通过其他控件立即传播
Person
实体中的更新,而无需调用table.refresh()
,例如 最佳答案
首先,请注意,如果您遵循expected pattern:
public class Person {
private final StringProperty firstName = new SimpleStringProperty();
public StringProperty firstNameProperty() {
return firstName ;
}
public final String getFirstName() {
return firstNameProperty().get();
}
public final void setFirstName(String firstName) {
firstNameProperty().set(firstName);
}
}
那么您的任何一个版本的代码都可以工作,而无需调用
table.refresh()
。这是PropertyValueFactory
的预期用途,从documentation可以很明显地看出来。不过,您是正确的,lambda表达式比
PropertyValueFactory
更好。除了您引用的原因外,与PropertyValueFactory
相比,使用lambda表达式还有其他主要优势。首先,也是最重要的一点,PropertyValueFactory
只是将属性的名称作为String
,这意味着没有针对它的编译时检查。因此,如果您拼写错误的属性名称:firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstname"));
这样可以很好地编译,并且您最终只会在该列中留空单元格。这可能很难调试(正如该网站上针对此类错误寻求帮助的问题数量所证明的那样)。
其次,
PropertyValueFactory
通过反射起作用,这比lambda表达式慢得多。这可能导致可测量的性能差异,例如在对具有大量数据的表进行排序时。引入
PropertyValueFactory
的原因基本上是历史性的。在Java 8之前,当然没有lambda表达式,因此没有此便利类的单元工厂的最小实现是通过匿名内部类:firstNameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<Person, String> cellData) {
return cellData.getValue().firstNameProperty();
}
});
由于该代码确实非常丑陋,因此JavaFX团队引入了
PropertyValueFactory
只是为了使该API易于使用。当使用Java 8及更高版本时,
PropertyValueFactory
实际上应被视为旧类,并且应首选lambda表达式。当然,早于Java 8的文档也仍然存在(实际上,您明确地从JavaFX 2链接了文档-尽管Javafx PropertyValueFactory not populating Tableview尚未更新),并且-坦率地说-太多其他作者复制了该文档。样式,没有经过适当考虑。完全弃用PropertyValueFactory
类可能是一个很好的案例。(所以:TL; DR:不,您没有丢失任何东西。)