在JavaFX WorkerStateEvent上编译lambda时出错
此代码不使用javacjdk8编译器编译在JavaFX WorkerStateEvent上编译lambda时出错,java,intellij-idea,lambda,javafx,Java,Intellij Idea,Lambda,Javafx,此代码不使用javacjdk8编译器编译 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 Ser
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 bug吗?我使用最新版本的Intellij Ultimate(14.1.1)。设置失败的签名是
public final void setOnFailed(EventHandler<WorkerStateEvent> value)
编辑:
使用plainjavac
编译非泛型版本会引发相同的错误:
src/stackoverflowfx/StackOverflowFX.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/stackoverflowfx/StackOverflowFX.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
所以这不是IDE的问题。对于这个特定的案例,我实际上会以不同的方式编写它。您已经知道触发的事件的来源是什么;这是您注册侦听器的
服务。所以你可以这么做
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()));
}
}
导入javafx.application.application;
导入javafx.concurrent.Service;
导入javafx.concurrent.Task;
导入javafx.stage.stage;
公共类ServiceTest扩展了应用程序{
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
public void start(Stage primaryStage)引发异常{
服务=新服务(){
@凌驾
受保护的任务createTask(){
返回null;
}
};
service.setOnFailed(事件->
System.out.println(event.getSource().getException().toString());
}
}
显然,您的代码中有足够的信息让编译器推断event
属于workerstatevent
类型,这应该允许您调用event.getSource().getException()
。我认为当您使用原始类型(Service
)而不是一般类型的对象(Service
等)时,类型推断由于某种原因失败了 嗯,看来Intellij在这一点上有点问题,因为自动补全在getException()
上运行得很好。谢谢,但问题更多的是lambda如何与泛型一起工作,以及Intellij为什么在编译阶段之前没有检测到这个错误。我独自一人纠正了这个问题。是的,只是提供了一个替代方案。但是,您的原始代码可以编译,所以这是一个IntelliJ bug。什么?你说我发布的代码片段是编译的?我还以为错误在自动完成中…啊,等等:对不起;我在Eclipse中自动修改了它。别理它。让我更新这个答案,因为我认为这个改变更好。是的,我同意。我先前的“忽略这一点”是为了纠正这一说法。看起来这可能是编译器规范中的错误和疏忽,因为在这种情况下,没有理由需要泛型服务类型来推断类型,但是由于不鼓励使用原始类型,这可能是一个没有意义的问题。
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()));
}
}