This is basically just a type matching issue.
TableColumn<S, T>
defines a method setCellValueFactory(Callback<CellDataFeatures<S,T>, ObservableValue<T>> factory)
.
Since you have defined the column as a TableColumn<Configuration, Long>
, its setCellValueFactory
is expecting a Callback<CellDataFeatures<Configuration, Long>, ObservableValue<Long>>
as the parameter; i.e. it is expecting something that defines a method
public ObservableValue<Long> call(CellDataFeatures<Configuration, Long> cellDataFeatures) ;
If you pass this as a lambda expression of the form
cellData -> <some expression>
then the compiler will infer that cellData
is a CellDataFeatures<Configuration, Long>
and will require that the expression evaluates to an ObservableValue<Long>
.
So cellData.getValue()
will evaluate to a Configuration
, and if you define the age
property in Configuration
as a LongProperty
, then of course cellData.getValue().ageProperty()
evaluates to a LongProperty
. This causes a type mismatch and the compiler complains. Remember that the compiler is expecting this expression to evaluate to an ObservableValue<Long>
; as you observed LongProperty
implements ObservableValue<Number>
, not ObservableValue<Long>
. Thus your expression evaluates to an ObservableValue<Number>
instead of the required type of ObservableValue<Long>
.
Both the fixes you mentioned work: changing the column to a TableColumn<Configuration, Number>
works because the compiler is then expecting a lambda expression evaluating to an ObservableValue<Number>
(which it is getting).
Calling asObject()
on the LongProperty
works too. As the Javadocs state, this method creates an ObjectProperty<Long>
that is bidirectionally bound to the LongProperty
. Since ObjectProperty<T>
implements ObservableValue<T>
, cellData.getValue().ageProperty().asObject()
is an ObservableValue<Long>
as required.