我有一个座位数组,数组有两个字符串(选中和空)。在鼠标单击时,我想遍历数组并找到所选的座位。当我按下按钮时,它说:
无法分配最终的局部变量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);
答案 0 :(得分:94)
关键是来自封闭类型的方法局部变量实际上是复制到匿名类的实例(这是因为激活帧问题,但我不会进一步详细说明与问题无关,这就是为什么它们需要是最终的,因为嵌套类型实例中的变量不再相同。
所以,这是第一个例子:
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
方法时,它会将run()
增加3。 (在这个例子中,它永远不会被调用,但它只是一个例子。)
因此,总而言之,您需要将变量seatno
从方法局部变量转换为封闭类型的实例变量。或者,如果它还没有,则需要删除最终修饰符,因为最终变量只能分配一次。
更新:在Java 8中,引入了有效最终变量的概念(参见Java Language Specification)。但是,在这篇文章的第一个例子中,变量a
被多次分配,这使它无法有效地成为最终版本。这意味着此示例仍然无法使用Java 8进行编译。(编译错误是“在封闭范围中定义的局部变量必须是最终的或有效的最终”)
答案 1 :(得分:4)
最终变量不能改变它的值(它与C / C ++中的const类似)。
你可能想让它成为一个类中的一个字段(当然没有final关键字),而不是一个函数内的局部变量。
答案 2 :(得分:4)
除了定义类成员变量之外,您还可以使用mutable int来实现相同的目标。
void foo() {
final MutableInt a = new MutableInt(3);
new Runnable() {
@Override
public void run() {
a.add(3);
}
};
}
由于MutableInt不是原始类型(因此通过引用传递)并且可以重新分配,所以它可以工作。
答案 3 :(得分:1)
我最近遇到了类似的问题。在我的例子中,更容易创建最终数组(或集合)并添加变量,我想在匿名类中更改为此数组,如下所示。
int a = 3;
final int[] array = new int[1];
array[0] = a;
new Runnable() {
@Override
public void run() {
array[0] += 3;
}
};
答案 4 :(得分:0)
在不知道seatno
的声明的情况下,我建议在mouseClicked()
方法中引入一个新的变量 not final,并执行与{{{{1}相同的工作1}}目前确实如此,因为变量似乎只在该方法中使用。
顺便说一下:将您的班级名称大写(seatno
应为data
)。看起来会更清楚。
答案 5 :(得分:0)
确保您的变量没有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"))