“从内部类引用的局部变量必须是final或有效的final”-如何解决?

时间:2018-08-22 11:54:29

标签: java

我见过其他具有类似问题的线程,但是在这些线程中,解决方案是创建一个带有值副本的最终变量,以使该变量有效地成为最终变量。但是,我的问题源于一个事实,即产生错误的变量是保存类实例的2D数组。

以下是发生错误的Controller类的代码:

package Controller;

import Model.Die;
import View.GameWindow;
import View.HelpWindow;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Controller {

private GameWindow view;
private static int pos[] = new int[2];
private Die diceLayout[][];
private String createdWord;

public Controller(){

    view = new GameWindow();
    addHelpListener();
    addSubmitListener();
    diceLayout = view.getDice();

}

private void submitWord(String word){
    boolean valid = checkValidWord(word);
    if(valid){
        System.out.println("The word ‘"+word+"‘ is valid.");
    }else{System.out.println("The word ‘"+word+"‘ is not valid.");}
}

private boolean checkValidWord(String word){
    boolean validSpell = validWordDic(word);
    boolean connected = checkWordConnected(word);
    if(validSpell&&connected){
        return true;
    }else{
        return false;
    }
}

private static boolean validWordDic(String word){
    word=word.toLowerCase();
    try {
        BufferedReader in = new BufferedReader(new FileReader("C:\\Users\\sambe\\Desktop\\IPT\\BoggleGame\\res\\dictionary.txt"));
        String str;
        while ((str = in.readLine()) != null) {
            if (str.indexOf(word) != -1) {
                return true;
            }
        }
        in.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return false;
}

public boolean checkWordConnected(String word){
    word = word.toLowerCase();
    String letters[] = word.split("");
    for(int i = 0; i<4; i++){
        for(int j = 0; j<4; j++){
            if(letters[0]==diceLayout[i][j].getText()){
                pos[0]=i;
                pos[1]=j;
            }
        }
    }
    return true;
}

private void addHelpListener(){
    view.getHelpButton().addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e) { 
            HelpWindow helpWin = new HelpWindow();
            System.out.println("done");
        } 
    });
}

private void addSubmitListener(){
    view.getSubmitButton().addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("done");
            if(view.getSubmitField().getText()!=null){
                submitWord(view.getSubmitField().getText());
            }else{
                submitWord(createdWord);
                createdWord="";
            }
            view.getSubmitField().setText("");
        } 
    });
}

private void addDiceListeners(){
    for(int i = 0; i<4; i++){
        for(int j = 0; j<4; j++){
            diceLayout[i][j].addActionListener(new ActionListener(){
                @Override
                public void actionPerformed(ActionEvent e){
                    diceLayout[i][j].setClicked(true); //Error Occurs here
                }
            });
        }
    }
}
}

如果有人对如何解决此问题有任何建议,将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:3)

这与数组无关,与循环计数器有关。由于ij并不是有效的最终形式(它们通过循环递增),因此不能在匿名类中使用它们。

diceLayout[i][j].setClicked(true);
           ^
       error here (and if you fixed that, it would appear at j)

您可以将Die提取到局部变量中,因此只能在侦听器外部访问ij

private void addDiceListeners()
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            Die die = diceLayout[i][j];
            die.addActionListener(new ActionListener()
            {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                    die.setClicked(true); 
                }
            });
        }
    }
}

答案 1 :(得分:1)

这里:

diceLayout[i][j].setClicked(true); //Error Occurs here

您的问题是i和j。这些是封闭方法中的 local 变量。 当然,这些是 loop 计数器,因此您不能将它们定为最终计数器。

这应该做:

for(int i = 0; i<4; i++) {
    for(int j = 0; j<4; j++) {
      final int finalRow = i;
      final int finalColumn = j;

然后使用刚创建的两个最终副本代替i和j。或者,按照其他答案的建议进行操作,然后获取要使用的实际Die对象(作为最终对象)。