关键是封闭类型中的方法局部变量实际上已 复制
到匿名类的实例中(这是由于激活框架的问题,但我将不做进一步的详细介绍,因为这与问题无关)。这就是为什么它们需要是final的原因,因为嵌套类型实例中的变量不再相同。
因此,这是第一个示例:
void foo() { int a = 3; new Runnable() { @Override public void run() { a += 3; } };}这不会编译,因为您无法在匿名类的方法中引用非最终变量。当您在的声明中添加最终修饰符时
a,的值
a将被复制到您定义的匿名类的创建实例中。但是,将不允许您更改的值
a,因为所做的更改对于
a声明位置的方法不可见。
但是,匿名类不是静态的,也就是说,它们具有对封闭实例的引用(除非声明它们的方法是静态的),您可以使用它来修改封闭实例的变量:
int a = 3;void foo() { new Runnable() { @Override public void run() { a += 3; } };}该示例确实进行了编译,
a每次
run()调用匿名类实例的方法时,它都会增加3 。(在此示例中,从不调用它,而只是一个示例。)
因此,总而言之,您需要将变量
seatno从方法局部变量转换为封闭类型的实例变量。或者,如果还没有,则需要删除final修饰符,因为final变量只能分配一次。
更新: 在Java 8中,引入了 有效的最终
变量的概念(请参阅Java语言规范)。但是,在此帖子的第一个示例中,变量
a被多次分配,这使变量无法有效地最终确定。这意味着该示例仍无法使用Java
8进行编译。(编译错误为“在封闭范围内定义的局部变量a必须是最终的或实际上是最终的”)



