我试图在javafx上调用此方法:TableColumn.setOnEditCommit
。该方法的定义如下:
public final void setOnEditCommit(EventHandler<CellEditEvent<S,T>> value) {
// ...
}
如您所见,它明确要求类型为EventHandler
的{{1}}(扩展了CellEditEvent
)。 Event
的定义:
EventHandler
很明显,要调用public interface EventHandler<T extends Event> extends EventListener {
void handle(T event);
}
(没有lamba),可以键入以下内容:
setOnEditCommit
注意:column.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent>() {
public void handle(CellEditEvent event) {
event.getTableView().doSomething();
}
});
是getTableView
的一种方法,而不是CellEditEvent
的一种方法。
到目前为止一切都很好。我遇到的问题是,使用lambda如果不进行强制转换,似乎不可能编写上述代码。也就是说,上面的lamba等效项是:
Event
这是问题所在。 Lambda不在乎该事件应该是column.setOnEditCommit(event -> event.getTableView().doSomething());
,因为CellEditEvent
方法明确声明了setOnEditCommit
的变量是EventHandler
。显然,在推断参数类型时,lanb会检出CellEditEvent
类定义,尤其是EventHandler
部分,然后确定T是<T extends Event>
,仅此而已,而不是t < em>扩展 Event
。在这种情况下,抛出的错误是找不到方法'getTableView'-因为Event
类没有该方法。
不仅如此,甚至没有明确指出参数类型无效:
Event
导致错误:
错误:(10,32)java:不兼容的类型:lambda表达式中的参数类型不兼容
我的问题是,为什么不正确地lambda推断该参数应为column.setOnEditCommit((TableColumn.CellEditEvent event) -> event.getTableView().doSomething());
(在这种情况下为T extends Event
)而不是CellEditEvent
,并且有任何方法可以解决该问题?
完整示例:
Event
答案 0 :(得分:2)
编译器没有该类型信息。 编译器具有的唯一信息是:
public interface EventHandler<T extends Event> extends EventListener {
void handle(T event);
}
现在您要像这样使用它:
import javafx.scene.control.TableColumn;
public class Main {
public static void main(String[] args) {
TableColumn column = null;
column.setOnEditCommit(event -> event.getTableView());
}
}
编译器应如何确定事件的类型? CellEditEvent类型不会出现在任何地方。
在这种情况下,您必须明确指定所需的类型。
column.setOnEditCommit((TableColumn.CellEditEvent event) -> event.getTableView().doSomething());
答案 1 :(得分:1)
显然,TableColumn
使用原始类型会导致发生此问题。这样就可以了:
TableColumn<SomeClass, SomeOtherClass> column = null;
column.setOnEditCommit(event -> event.getTableView());
不仅如此,而且:
TableColumn<?, ?> column = null;
column.setOnEditCommit(event -> event.getTableView());
但这不会:
TableColumn column = null;
column.setOnEditCommit(event -> event.getTableView());