Java Lamba参数类型无法正确推断

时间:2018-08-09 15:46:27

标签: java lambda

我试图在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

2 个答案:

答案 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());