这是代码片段的一部分:
for (int col=1;col<=7;col++) {
for (int row=2;row<=31;row++) {
if (col!=4) {
b = new Button();
b.setText(Seat.calcID(row, col));
b.setMinSize(2, 2);
b.setFont(new Font(8));
addableSeat.change(x, row, col);
System.out.println(row+" "+col);
b.setOnAction(e->{
book.addSeat(Seat.genSeat(x, row, col));
System.out.println(">>>"+addableSeat.accessId()+"<<<");
});
no=(col>4)?col+1:col;
grid.setConstraints(b,no,row);
grid.getChildren().add(b);
}
}
}
存在一个错误,指出事件处理程序中的变量“ row”和“ col”必须是最终的或实际上是最终的。我该如何实现?
如果您需要其他代码段,我愿意提供。谢谢!
答案 0 :(得分:1)
这是因为预期row
和col
的值会通过row++
和col++
随时间变化,因此编译器知道它都不是{{1 }},也不是有效地 final
。
(我能想到的)唯一的简单方法是声明其他局部变量。
final
如果您想要一些更高级的方法,可以使用这种“包装”方法。
final int r = row;
final int c = col;
b.setOnAction(e->{
book.addSeat(Seat.genSeat(x, r, c));
System.out.println(">>>"+addableSeat.accessId()+"<<<");
});
之所以可行,是因为final IntegerProperty col = new SimpleIntegerProperty();
final IntegerProperty row = new SimpleIntegerProperty();
for (col.set(1);col.get()<=7;col.set(col.get()+1)) {
for (row.set(2);row.get()<=31;row.set(row.get()+1)) {
if (col.get()!=4) {
...
...
b.setOnAction(e->{
book.addSeat(Seat.genSeat(x, row.get(), col.get()));
// I can even change value from the handler
row.set(Integer.MAX_VALUE);
});
}
}
}
和row
现在是对象类型(而不是原始类型),而它们是col
。由于对象引用已传递到final
中,因此处理程序可以自由使用它们和包装的值-这包括更改内部值。
c0der提到的方法只是对此的一种变体。将值包装在原始包含类中,而不是创建用于包装值的新对象实例。
但是,请不要误解我的意思-这种方法对您的情况无效无效。我之所以决定在此加入,是因为这是避免EventHandler
并有效解决final
问题的另一种方法。
使用包装方法(c0der和我的方法)将产生不同的行为。这是因为final
和row
的值现已共享。由于col
循环执行得如此之快,以至于几乎任何人都不可能触发其间的事件,因此for
和row
的最终值将变为col
和{ {1}}。这意味着 all 32
将实际上成为8
。
答案 1 :(得分:1)
在大多数情况下,采用Jai提出的简单通用解决方案。
在某些情况下,您可能希望将row
和col
声明为类变量(字段):
private int row, col;
for (col=1;col<=7;col++) {
for (row=2;row<=31;row++) {
if (col!=4) {
...
...
b.setOnAction(e->{
book.addSeat(Seat.genSeat(x, row, col));
});
}
}
}