在 JavaFX WorkerStateEvent 上编译 lambda 时出错
Error compiling lambda on JavaFX WorkerStateEvent
此代码无法使用 javac JDK8 编译器进行编译。
public class Test extends Application {
public static void main(String[] args) {
launch(Test.class);
}
@Override
public void start(Stage primaryStage) throws Exception {
Service service = new Service() {
@Override
protected Task createTask() {
return null;
}
};
service.setOnFailed(event -> System.out.println(event.getSource().getException().toString()));
}
}
错误是
java: cannot find symbol
symbol: method getException()
location: class java.lang.Object
IntelliJ 告诉我一切正常,如果我在 event.getSource()
上手动添加强制转换,编译工作正常,但 Intellij 告诉我强制转换是多余的。
是否存在 Intellij 错误?我使用的是最新版本的 Intellij Ultimate (14.1.1)。
setOnFailed
的签名是
public final void setOnFailed(EventHandler<WorkerStateEvent> value)
所以你需要提供一个EventHandler<WorkerStateEvent>
。 WorkerStatEvent
has the method public Worker getSource()
that returns a javafx.concurrent.Worker
. Your lambda effectively just provides an EventHandler<javafx.event.Event>
. The method getSource()
of javafx.event.Event
只是返回一个 java.util.EventObject
,它没有 WorkerStateEvent
有的方法 getException()
。
使用泛型:
final EventHandler<WorkerStateEvent> handler = event ->
System.out.println(event.getSource().getException().toString());
service.setOnFailed(handler);
编辑:
用普通 javac
编译非通用版本会抛出同样的错误:
src/Whosebugfx/WhosebugFX.java:29: error: cannot find symbol
final EventHandler handler = event -> System.out.println(event.getSource().getException().toString());
^
symbol: method getException()
location: class Object
Note: src/Whosebugfx/WhosebugFX.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
所以这不是 IDE 问题。
对于这个具体案例,我实际上会以不同的方式编写。您已经知道触发事件的来源是什么;它是您注册侦听器的 service
。所以你可以做
service.setOnFailed(event ->
System.out.println(service.getException().toString());
我不太明白为什么编译器不能从你的代码中推断出类型,但如果你正确地键入服务,为它的泛型类型提供一个参数,那么它编译得很好:
import javafx.application.Application;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.stage.Stage;
public class ServiceTest extends Application{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Service<Void> service = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return null;
}
};
service.setOnFailed(event ->
System.out.println(event.getSource().getException().toString()));
}
}
您的代码中显然有足够的信息供编译器推断 event
属于 WorkerStateEvent
类型,这应该允许您调用 event.getSource().getException()
。我认为当您使用原始类型 (Service
) 而不是一般类型的对象 (Service<Void>
等) 时,类型推断会因某种原因而失败。
此代码无法使用 javac JDK8 编译器进行编译。
public class Test extends Application {
public static void main(String[] args) {
launch(Test.class);
}
@Override
public void start(Stage primaryStage) throws Exception {
Service service = new Service() {
@Override
protected Task createTask() {
return null;
}
};
service.setOnFailed(event -> System.out.println(event.getSource().getException().toString()));
}
}
错误是
java: cannot find symbol
symbol: method getException()
location: class java.lang.Object
IntelliJ 告诉我一切正常,如果我在 event.getSource()
上手动添加强制转换,编译工作正常,但 Intellij 告诉我强制转换是多余的。
是否存在 Intellij 错误?我使用的是最新版本的 Intellij Ultimate (14.1.1)。
setOnFailed
的签名是
public final void setOnFailed(EventHandler<WorkerStateEvent> value)
所以你需要提供一个EventHandler<WorkerStateEvent>
。 WorkerStatEvent
has the method public Worker getSource()
that returns a javafx.concurrent.Worker
. Your lambda effectively just provides an EventHandler<javafx.event.Event>
. The method getSource()
of javafx.event.Event
只是返回一个 java.util.EventObject
,它没有 WorkerStateEvent
有的方法 getException()
。
使用泛型:
final EventHandler<WorkerStateEvent> handler = event ->
System.out.println(event.getSource().getException().toString());
service.setOnFailed(handler);
编辑:
用普通 javac
编译非通用版本会抛出同样的错误:
src/Whosebugfx/WhosebugFX.java:29: error: cannot find symbol
final EventHandler handler = event -> System.out.println(event.getSource().getException().toString());
^
symbol: method getException()
location: class Object
Note: src/Whosebugfx/WhosebugFX.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
所以这不是 IDE 问题。
对于这个具体案例,我实际上会以不同的方式编写。您已经知道触发事件的来源是什么;它是您注册侦听器的 service
。所以你可以做
service.setOnFailed(event ->
System.out.println(service.getException().toString());
我不太明白为什么编译器不能从你的代码中推断出类型,但如果你正确地键入服务,为它的泛型类型提供一个参数,那么它编译得很好:
import javafx.application.Application;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.stage.Stage;
public class ServiceTest extends Application{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Service<Void> service = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return null;
}
};
service.setOnFailed(event ->
System.out.println(event.getSource().getException().toString()));
}
}
您的代码中显然有足够的信息供编译器推断 event
属于 WorkerStateEvent
类型,这应该允许您调用 event.getSource().getException()
。我认为当您使用原始类型 (Service
) 而不是一般类型的对象 (Service<Void>
等) 时,类型推断会因某种原因而失败。