java:是否可以为Buttons数组设置lambda表达式是for循环? 如果是这样的话?
我希望能够做到这样的事情:
for(i = 0; i { button[i].setDisable(true) } ); }
但是,我得到一个错误说"local variables referenced from a lambda expression must be final or effectively final"
。 我怎么还能像上面的代码那样做(如果可能的话)? 如果无法完成,应该做些什么来获得类似的结果呢?
正如错误消息所示,从lambda表达式引用的局部变量必须是最终的或有效的final(“有效最终”意味着编译器可以使它最终为您)。
简单的解决方法:
for(i = 0; i < 10; i++) { final int ii = i; button[i].setOnAction( ae -> { button[ii].setDisable(true) } ); }
由于您使用的是lambdas,因此您也可以从Java 8的其他function(如流)中受益。
例如, IntStream
:
支持顺序和并行聚合操作的一系列原始int值元素。 这是Stream的int原始特化。
可以用来替换for循环:
IntStream.range(0,10).forEach(i->{...});
所以现在你有一个可以用于你的目的的索引:
IntStream.range(0,10) .forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
您还可以从数组生成流:
Stream.of(button).forEach(btn->{...});
在这种情况下,您将没有索引,因此@shmosel建议您可以使用事件的来源:
Stream.of(button) .forEach(btn->btn.setOnAction(ea->((Button)ea.getSource()).setDisable(true)));
编辑
正如@James_D建议的那样,这里不需要向下转发:
Stream.of(button) .forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
在这两种情况下,您还可以从并行操作中受益:
IntStream.range(0,10).parallel() .forEach(i->button[i].setOnAction(ea->button[i].setDisable(true))); Stream.of(button).parallel() .forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
使用Event
获取源Node
。
for(int i = 0; i < button.length; i++) { button[i].setOnAction(event ->{ ((Button)event.getSource()).setDisable(true); }); }
Lambda表达式实际上就像一个在流上工作的匿名方法。 为了避免任何不安全的操作,Java已经使得没有可以修改的外部变量可以在lambda表达式中访问。
为了解决它,
final int index = button [i]; 并在lambda表达式中使用index而不是i 。
你说如果按下按钮,但在你的例子中,列表中的所有按钮都将被禁用。 尝试将侦听器关联到每个按钮,而不是仅禁用它。
对于逻辑,你的意思是这样的:
Arrays.asList(buttons).forEach( button -> button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { button.setEnabled(false); } }));
我也喜欢Sedrick的答案,但你必须在循环中添加一个动作监听器。