在完成“別踩白塊”的課設時,遇到了按鈕數組註冊監聽的問題,現將問題和解決辦法記錄如下:
問題
如下設置監聽會提示:從內部引用的本地變量必須是最終變量或實際上的最終變量(使用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);
}
}