为什么我突然需要将变量声明为" final"将ActionListener添加到按钮时?

时间:2012-07-09 21:27:44

标签: java jframe jbutton actionlistener final

  

可能重复:
  Why are only final variables accessible in anonymous class?

这是我为课堂创作的“随机数学游戏”的代码:

package RandomMathGame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class RandomMathGame {

    public static void main(String[] args) {
        RandomProblemGenerator randomProblems = new RandomProblemGenerator(10);
        final int numberProblems = 10;
        int correctScore = 0;
        JPanel panel = new JPanel();
       int answer;
        int correctAnswer;
        JLabel[] mathProblems = new JLabel[numberProblems];
        final JTextField[] mathAnswers = new JTextField[numberProblems];
        JLabel[] correctYesNo = new JLabel[numberProblems];
        final JLabel score = new JLabel(correctScore + "/10");
        JButton submit = new JButton("Submit");
        for (int i = 1; i <= numberProblems; i++)
        {
            final int X = randomProblems.createNumberX();
            final int Y = randomProblems.createNumberY();

            mathProblems[i] = new JLabel("" + X + " * " + Y + " = ");
            mathAnswers[i] = new JTextField();


             answer = Integer.parseInt(mathAnswers[i].getText());
             correctAnswer = X * Y;

            if (answer == correctAnswer)
            {
                correctYesNo[i] = new JLabel("Correct answer; good job!");
                correctScore = correctScore + 1;
            }
            else
            {
               correctYesNo[i] = new JLabel("Incorrect answer; try again!");

            }
             panel.add(mathProblems[i]);
             panel.add(mathAnswers[i]);
             panel.add(correctYesNo[i]);
            }
      submit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                score.setText("Score: " + correctScore + "/10");
            }
        });



        panel.add(submit);
        panel.add(score);

        JFrame gameFrame = new JFrame();
        gameFrame.setTitle("Random Math Game");
        gameFrame.setSize(150, 150);
        gameFrame.setVisible(true);
        gameFrame.setContentPane(panel);



        }
  }

我收到一个错误,即在ActionListener可以使用correctScore变量之前必须将其声明为final。但是当我将correctScore设置为final时,会导致各种其他错误。任何人都可以想办法解决这个问题吗?

3 个答案:

答案 0 :(得分:3)

要将局部变量传递给匿名类,它必须是最终的 - 这是Java语言的一部分。现在,当一个原始变量是最终变量时,你无法对其进行修改,因此在进行correctScore最终时会遇到问题。

解决方法是在addActionListener调用之前使用临时变量:

final int temp = correctScore;

并在temp方法中使用actionPerformed变量。

请注意,当您这样做时,以后对correctScore的任何更改都会反映在temp的值中。

答案 1 :(得分:0)

在Java中,如果要从本地类(

)中访问本地变量
new ActionListener() {
...
...
}

是一个新的本地匿名类) 必须将变量声明为final。

如果没有final修饰符,本地类无法访问封闭方法的局部变量 例如:

public class Main {
    private int b=5;
    public void bla() {
    int a = 5;
    ActionListener al = new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            a = 4; // Error. a must be final
            b = 5; // OK!
        }
    };
  }
}

您问题的可能解决方案是使用在任何方法之外声明的变量(上例中的b)

答案 2 :(得分:-1)

您收到该消息是因为您已将JLabel评分声明为最终评分。您不能使用非final变量来设置最终变量的值。我不知道你为什么要进入决赛。只需删除该决赛。

编辑:我错过了在我第一次阅读时,correctScore是一个函数变量。如果你把它变成一个类变量,我想你的很多问题都会消失。