Below are three ways to assign a CellValueFactory
to a TableColumn
in JavaFX. The first one uses an anonymous class, the second one a lambda and the third one a PropertyValueFactory
.
My question is about the third way, using a PropertyValueFactory
.
Having examined the source code:
I can't see what advantage is conferred by using this class.
In the source code of PropertyValueFactory, there is a note that they "try to improve performance in large tables" by caching a 'PropertyReference' member variable. In connection with this note, a reference to RT-13937 is mentioned. I cannot find this RT online anymore.
The following things are confused in my mind.
Is there some specific use case that is addressed by using the PropertyValueFactory
technique that cannot be addressed using either of the other two techniques?
Is the caching of the PropertyReference
member variable meant to address the slowness of using the PropertyValueFactory
class in large tables, that slowness being caused by that class's use of reflection, or is 'PropertyValueFactory' class itself meant to address the slowness of large tables generally?
/**
First using an anonymous class
*/
TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name");
firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<Person, String> p) {
// p.getValue() returns the Person instance for a particular TableView row
return p.getValue().firstNameProperty();
}
});
/**Second using lambda
*/
TableColumn<Person, String> firstNameCol =new TableColumn<>("First Name");
firstNameCol.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
/**Finally using PropertyValue
*/
TableColumn<Person, String> firstNameCol =new TableColumn<>("First Name");
firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));
In your use case, there isn't any significant differences using PropertyValueFactory
over using lambda/anonymous classes.
As far as I know these are the reasons for using PropertyValueFactory
:
Therefore if you are looking for use-case for PropertyValueFactory
, then the most fitting use-case is when your properties are normal POJO properties.
Consider this:
public class Person {
private String firstName;
private String lastName;
public final String getFirstName() { return firstName; }
public final void setFirstName(String firstName) { this.firstName = firstName; }
public final String getLastName() { return lastName; }
public final void setLastName(String lastName) { this.lastName = lastName; }
}
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<Person, String> p) {
return new SimpleStringProperty(getPropertyReflectively(p.getValue(), "firstName", String.class));
}
});
private static <T> T getPropertyReflectively(Object bean, String propertyName, Class<T> propertyType) {
// Implementation to get property value reflectively
}
So there are two things observed:
PropertyValueFactory
does that for you?StringProperty
, and also doing reflection every time you scroll your big one-million-entry table.I believe the caching mentioned is used for observation #2. You can continue to "decipher" the codes if you want to be sure, because I definitely didn't attempt to do so.