Java8Lambda语法更改
我遇到了一个问题,Lambda的允许语法在java编译器的1.8.0_05和1.8.0_20(beta版)之间发生了变化 例如:Java8Lambda语法更改,java,lambda,compiler-errors,java-8,Java,Lambda,Compiler Errors,Java 8,我遇到了一个问题,Lambda的允许语法在java编译器的1.8.0_05和1.8.0_20(beta版)之间发生了变化 例如: package scratch; import javafx.scene.control.MenuItem; public class Test { public void test() { MenuItem mi = new MenuItem(); //This compiles anywhere
package scratch;
import javafx.scene.control.MenuItem;
public class Test
{
public void test()
{
MenuItem mi = new MenuItem();
//This compiles anywhere
mi.setOnAction(e -> System.out.println("hi"));
//as does this
mi.setOnAction(e -> {System.out.println("hi");});
//This doesn't on build 1.8.0_20-ea-b13 - but does on build 1.8.0_05-b13
mi.setOnAction(e -> (System.out.println("hi")));
}
}
我想知道的是,最后一个示例是有效的Lambda表达式吗?他们刚刚加强了编译器验证?或者最新的1.8编译器中是否存在bug
最新编译器打印的错误为:
/scratch/src/scratch/Test.java:18: error: method setOnAction in class MenuItem cannot be applied to given types;
mi.setOnAction(e -> (System.out.println("hi")));
^
required: EventHandler<ActionEvent>
found: (e)->(Syst[...]hi"))
reason: argument mismatch; bad return type in lambda expression
missing return value
1 error
/scratch/src/scratch/Test.java:18:错误:类MenuItem中的方法setOnAction无法应用于给定类型;
mi.setOnAction(e->(System.out.println(“hi”));
^
必需:EventHandler
发现:(e)->(系统[…]hi”))
原因:参数不匹配;lambda表达式中的返回类型错误
缺少返回值
1错误
编辑(因为我似乎无法格式化回复中的评论):
setOnAction方法的实现是:
public final void setOnAction(EventHandler<ActionEvent> value) {
onActionProperty().set( value);
}
public final void setOnAction(EventHandler值){
onActionProperty().set(值);
}
和事件处理程序:
@FunctionalInterface
public interface EventHandler<T extends Event> extends EventListener {
/**
* Invoked when a specific event of the type for which this handler is
* registered happens.
*
* @param event the event which occurred
*/
void handle(T event);
}
@functioninterface
公共接口EventHandler扩展了EventListener{
/**
*当此处理程序所针对的类型的特定事件发生时调用
*这种情况经常发生。
*
*@param event发生的事件
*/
无效句柄(T事件);
}
在Java编程语言中,方法调用表达式是一种结构,它可以出现在需要表达式或需要语句的两个位置
因此,对于用例e->System.out.println(“hi”),您可以使用简化的表达式形式param->expression
即使该方法返回void
。由于此处预期的函数签名是T->void
,因此包含void
方法的单个调用的lambda表达式在此上下文中有效
当您尝试在需要表达式的不同上下文中使用表达式语句时,情况会发生变化。比较:
当且仅当一个方法调用(§15.12)调用了一个不返回值的方法,即一个声明无效的方法(§8.4)时,表达式不表示任何内容。此类表达式只能用作表达式语句(§14.8),因为表达式出现的所有其他上下文都要求表达式表示某些内容
正式应用此规则,即使像在(System.out.println(“hi”)
中那样简单地在其周围加上大括号也是无效的,因为这是一个复合表达式,试图在需要“实表达式”(返回值)的上下文中使用声明的void
方法的方法调用
因此,使用无效表达式的lambda表达式在mi.setOnAction(e->(System.out.println(“hi”));
中也不可能是有效的。消息有点误导。编译器似乎关注的是形式的表达式(无论什么)
,是非语句表达式,因此在void
上下文中无效。但是,报告将void
方法调用放在圆括号中的初始错误会更有用
您不能将
(…)
放在无效方法调用周围的规则没有改变,因此错误是较旧的编译器接受此语法,现在似乎已经修复。menuItem.setOnAction()的返回类型是什么
新类路径中的方法?@user2163960,请在问题中添加:MenuItem.setOnAction()的定义,以及它作为参数接收的接口。如果方法重载,请包括所有重载方法。谢谢。您是否知道这是一个预期的更改,或者可能是另一个错误修复的副作用?我认为,这与此相关(请参阅“应始终使用lambda body结构来消除重载解析的歧义”)错误报告的直接链接如下: