I'm trying to call this method on javafx: TableColumn.setOnEditCommit
. This method's definition is the following:
public final void setOnEditCommit(EventHandler<CellEditEvent<S,T>> value) {
// ...
}
As you can see, it explicitely requires an EventHandler
of type CellEditEvent
(which extends Event
). The EventHandler
's definition:
public interface EventHandler<T extends Event> extends EventListener {
void handle(T event);
}
Obvious enough, to call setOnEditCommit
(without lamba), one would type this:
column.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent>() {
public void handle(CellEditEvent event) {
event.getTableView().doSomething();
}
});
Note: getTableView
is a method of CellEditEvent
, but not of Event
.
All nice so far. The problem I've come into is that writing the above code seems to be impossible using lambda, without casting. That is, the lamba equivalent for the above is:
column.setOnEditCommit(event -> event.getTableView().doSomething());
Here's the problem. Lambda
doesn't care that the event should be a CellEditEvent
because the setOnEditCommit
method explicitely states the EventHandler
's vararg is a CellEditEvent
.
Apparently, when inferring argument types, lambda checks out the EventHandler
class definition, in particular the <T extends Event>
part, and then decides that T is an Event
, and that's it, not that t extends Event
. In this case, the error thrown is that method 'getTableView' is not found - because the Event
class doesn't have that method.
Not only that, but not even explicitely stating the argument type doesn't work:
column.setOnEditCommit((TableColumn.CellEditEvent event) -> event.getTableView().doSomething());
Results in the error:
Error:(10, 32) java: incompatible types: incompatible parameter types in lambda expression
My question is: Why doesn't lambda correctly infer that the argument should be T extends Event
(CellEditEvent
in this case), not Event
, and is there any way to fix that?
Full example:
import javafx.scene.control.TableColumn;
public class Main {
public static void main(String[] args) {
TableColumn column = null;
column.setOnEditCommit(event -> event.getTableView());
}
}
Apparently using raw types for the TableColumn
causes this issue to happen. So this will work:
TableColumn<SomeClass, SomeOtherClass> column = null;
column.setOnEditCommit(event -> event.getTableView());
Not only that, but also this:
TableColumn<?, ?> column = null;
column.setOnEditCommit(event -> event.getTableView());
But this will not:
TableColumn column = null;
column.setOnEditCommit(event -> event.getTableView());