无法分配最终的局部变量

2022-09-01 04:48:37

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

不能分配最终的局部变量 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);

答案 1

关键是来自封闭类型的方法局部变量实际上被复制到匿名类的实例中(这是因为激活帧问题,但我不会进一步详细介绍,因为这与问题并不真正相关),这就是为什么它们需要是最终的,因为嵌套类型实例中的变量不再相同。

所以,这是第一个例子:

void foo() {
    int a = 3;
    new Runnable() {
        @Override
        public void run() {
            a += 3;
        }
    };
}

这不会编译,因为您无法在匿名类的方法中引用非最终变量。当您将最终修饰符添加到 的声明中时,的值将被复制到您定义的匿名类的创建实例中。但是,将不允许您更改 的值,因为更改对于声明的方法不可见。aaaa

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

int a = 3;

void foo() {
    new Runnable() {
        @Override
        public void run() {
            a += 3;
        }
    };
}

此示例进行编译,每次调用匿名类实例的方法时,它都会增加 3。(在此示例中,它从未被调用,但它只是一个示例。arun()

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

更新:在Java 8中,引入了有效最终变量的概念(参见Java语言规范)。但是,在本文的第一个示例中,变量被多次分配,这阻止了它有效地最终。这意味着此示例仍无法使用 Java 8 进行编译。(编译错误是“在封闭作用域中定义的局部变量 a 必须是最终变量或实际上是最终变量”)a


答案 2

最后一个变量不能改变它的值(它类似于C / C++中的const)。

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


推荐