无法分配最终的局部变量

36 java swing final mouselistener

我有一个座位数组,数组有两个字符串(选中和空).在鼠标单击时,我想遍历数组并找到所选的座位.当我按下按钮时,它说:

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

    JButton btnContinue = new JButton("Next");
    btnContinue.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent arg0) {

            for(int x=0;x<17;x++){
                if(anArray[x]=="selected"){

                    seatno = anArray[x];
                }
            }

            data page=new data(newfrom,newto,newtime,date2,seatno);
            page.setVisible(true);
            setVisible(false);
        }
    });
    btnContinue.setBounds(358, 227, 62, 23);
    contentPane.add(btnContinue);
Run Code Online (Sandbox Code Playgroud)

Mic*_*ßer 94

关键是来自封闭类型的方法局部变量实际上被复制到匿名类的实例(这是因为激活框架问题,但我不会进一步详细说明,因为这与问题无关),这就是他们需要最终的原因,因为嵌套类型实例中的变量不再相同.

所以,这是第一个例子:

void foo() {
    int a = 3;
    new Runnable() {
        @Override
        public void run() {
            a += 3;
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

这不会编译,因为您无法在匿名类的方法中引用非final变量.在声明中添加final修饰符时a,a会将值复制到已定义的匿名类的已创建实例中.但是,您将不被允许更改值a,因为a声明的方法不会显示更改.

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

int a = 3;

void foo() {
    new Runnable() {
        @Override
        public void run() {
            a += 3;
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

这个例子进行编译,a每次run()调用匿名类'实例的方法时它都会增加3 .(在这个例子中,它永远不会被调用,但它只是一个例子.)

因此,总而言之,您需要将变量seatno从方法局部变量转换为封闭类型的实例变量.或者,如果它还没有,则需要删除最终修饰符,因为最终变量只能分配一次.

更新:在Java 8中,引入了有效最终变量的概念(请参阅Java语言规范).但是,在这篇文章的第一个例子中,变量a被多次分配,这使它无法有效地最终.这意味着此示例仍然无法使用Java 8进行编译.(编译错误是"在封闭范围中定义的局部变量必须是最终的或有效的最终")