Java 无法指定最终的局部变量

Java 无法指定最终的局部变量,java,swing,final,mouselistener,Java,Swing,Final,Mouselistener,我有一个席位数组,该数组有两个字符串(selected和empty)。单击鼠标,我想遍历数组并找到所选的座位。当我按下按钮时,它会说: 无法指定最终局部变量seatno,因为它是在封闭类型中定义的 JButton btnContinue=新的JButton(“下一步”); btnContinue.addMouseListener(新的MouseAdapter(){ 公共无效鼠标单击(鼠标事件arg0){ 对于(int x=0;x,在不知道seatno的声明的情况下,我建议在mouseClicke

我有一个席位数组,该数组有两个字符串(selected和empty)。单击鼠标,我想遍历数组并找到所选的座位。当我按下按钮时,它会说:

无法指定最终局部变量seatno,因为它是在封闭类型中定义的

JButton btnContinue=新的JButton(“下一步”);
btnContinue.addMouseListener(新的MouseAdapter(){
公共无效鼠标单击(鼠标事件arg0){

对于(int x=0;x,在不知道
seatno
的声明的情况下,我建议在
mouseClicked()
方法中引入一个新变量,该变量不是final,并且执行与
seatno
当前相同的工作,因为该变量似乎只在该方法中使用


顺便说一下:将类名大写(
data
应该是
data
)。这样看起来更清晰。

最终变量不能更改其值(类似于C/C++中的const)


您可能希望使其成为类中的字段(当然没有final关键字),而不是函数中的局部变量。

确保您的变量没有
final
修饰符

//final, can be set only when the object is created.
private final String seatno;

//no final modifier, the value can be set every time you "want"
private String seatno;
此外,要比较字符串,应使用
equals

if(anArray[x].equals("selected"))

关键是封闭类型中的方法局部变量实际上被复制到了匿名类的实例中(这是因为激活框架的问题,但我不会更详细,因为这与问题并不相关),这就是为什么它们必须是final,因为嵌套类型实例中的变量不再相同

下面是第一个例子:

void foo() {
    int a = 3;
    new Runnable() {
        @Override
        public void run() {
            a += 3;
        }
    };
}
这不会编译,因为您无法在匿名类的方法中引用非final变量。当您向
a
的声明添加final修饰符时,
a
的值将复制到您定义的匿名类的创建实例中。但是,您将不允许更改
a的值
,因为声明
a
的方法看不到更改

但是,匿名类不是静态的,也就是说,它们具有对封闭实例的引用(除非声明它们的方法是静态的),您可以使用该引用修改封闭实例的变量:

int a = 3;

void foo() {
    new Runnable() {
        @Override
        public void run() {
            a += 3;
        }
    };
}
此示例确实进行了编译,并且每次调用匿名类实例的
run()
方法时,它都会将
a
增加3。(在本示例中,它从未被调用,但只是一个示例。)

因此,总而言之,您需要将变量
seatno
从方法局部变量转换为封闭类型的实例变量。或者,如果仍然是,您需要删除final修饰符,因为final变量只能赋值一次


更新:在Java 8中,引入了有效最终变量的概念(请参阅)。但是,在本文的第一个示例中,变量
a
被分配了多次,这使得它无法有效最终。这意味着此示例仍然没有使用Java 8编译。(编译错误为“在封闭范围内定义的局部变量必须是final或有效final”)

除了定义类成员变量,还可以使用可变int来实现相同的目标

void foo() {
    final MutableInt a = new MutableInt(3);
    new Runnable() {
        @Override
        public void run() {
           a.add(3);
        }
    };
}

因为MutableInt不是基元类型(因此通过引用传递),可以重新分配,所以这是可行的。

我最近遇到了类似的问题。在我的例子中,创建最终数组(或集合)和向该数组添加我想在匿名类中更改的变量更容易,如下所示

   int a = 3;
   final int[] array = new int[1];
   array[0] = a;
   new Runnable() {
       @Override
       public void run() {
           array[0] += 3;
       }
   };

您的
seatno
变量中有最后一个关键字。注意:MutableInt需要Apache Commons Lang。很好,谢谢。MutableInt比AtomicInteger更方便,因为代码气味更少(需要的代码更少)
   int a = 3;
   final int[] array = new int[1];
   array[0] = a;
   new Runnable() {
       @Override
       public void run() {
           array[0] += 3;
       }
   };