繁体   English   中英

无法分配最终的局部变量

[英]The final local variable cannot be assigned

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

最终局部变量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);

关键是实际上封闭类型中的方法局部变量复制到匿名类的实例中(这是由于激活框架的问题,但我将不做进一步的详细介绍,因为这与问题无关)。这就是为什么它们需要是final的原因,因为嵌套类型实例中的变量不再相同。

因此,这是第一个示例:

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

这不会编译,因为您无法在匿名类的方法中引用非最终变量。 当您添加final修饰符来声明a ,值了a会被复制到您所定义的匿名类的创建的实例。 然而,你将不会被允许改变的值a ,因为变化将是不可见的,其中方法a被宣布。

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

int a = 3;

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

这个例子确实编译,它会增加a每次时间3 run()匿名类的实例的方法被调用。 (在此示例中,从不调用它,而只是一个示例。)

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

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

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

您可能希望使其成为类中的字段(当然没有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声明的seatno ,我建议在mouseClicked()方法中引入一个新变量,该变量不是 final的,并且与seatno当前所做的工作相同,因为该变量似乎仅在该方法内部使用。

顺便说一句:大写您的类名( data应为Data )。 看起来会更加清晰。

确保您的变量没有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"))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM