在完成“别踩白块”的课设时,遇到了按钮数组注册监听的问题,现将问题和解决办法记录如下:
问题
如下设置监听会提示:从内部引用的本地变量必须是最终变量或实际上的最终变量(使用final修饰的变量)此处的错误为变量i,并非mBolk数组。
for(int i=0;i<mBolk.length;i++){
mBolk[i] = new Bolk();
mBolk[i].addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
if( mBolk[i].getValue()){
mBolk[i].setValue(false);
mBolk[i].set_Color();
}
}
});
panel.add(mBolk[i]);
}
问题分析
这个问题在内部类的使用过程中比较常见,为内部类调用外部变量时必须保证外部变量时final类型的,即为最终变量。此处调用的为局部变量,局部变量不存放在对象所在的存储区中,即不予actionPerformed()方法共享存储区,在形式上来说即为方法中的方法调用了存放在运行栈上的局部变量(某种意义上来说感觉像内部类调用栈上的变量),所以需要将局部变量设置为最终变量,但是设置为最终变量后,变量i将失去原有的功能,所以在此处进入一个死循环。
解决方式
错误思路:设置监听的时候就决定该按钮监听方法,在监听方法中,希望传入按钮,对按钮进行操作,即通过传入不同的按钮,来实现不同的方法。
解决思路:在监听方法获取响应的按钮,然后对按钮执行操作。
区别:解决思路中所有的按钮只需要注册同一个监听方法,在方法中判断按钮需要执行的操作,错误思路中将不同的按钮都注册监听,造成了代码的无必要重复。
for(int i=0;i<mBolk.length;i++){
mBolk[i] = new Bolk();
mBolk[i].addActionListener(this);
panel.add(mBolk[i]);
}
public void actionPerformed(ActionEvent event){
Bolk bolk = (Bolk)event.getSource();
if(Game.isSuccess(bolk)){
grade++;
}else{
System.out.println(grade);
}
}