0

Possible Duplicate:
Why are only final variables accessible in anonymous class?

This is the code I have for a "random math game" I'm creating for 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);



        }
  }

I'm getting an error that the correctScore variable has to be declared as final before it can be used by the ActionListener. But when I set correctScore as a final, it causes all kinds of other errors. Can anybody think of a way to resolve this?

Community
  • 1
  • 1
commandrix
  • 63
  • 3
  • 10

3 Answers3

3

To pass a local variable to an anonymous class, it has to be final - that is part of the Java language. Now when a primitive variable is final, you can't modify it, hence the issues you get when making correctScore final.

A workaround is to use a temporary variable right before the addActionListener call:

final int temp = correctScore;

and use that temp variable in your actionPerformed method.

Note that when you do that, any future changes to correctScore will not be reflected in the value of temp.

assylias
  • 321,522
  • 82
  • 660
  • 783
0

In Java, If you want to access a local variable from within a local class (

new ActionListener() {
...
...
}

is a new local anonymous class) the variable must be declared as final.

Local classes cannot access local variable of the enclosing method without final modifier for example:

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!
        }
    };
  }
}

A possible solution to your problem is using variables declared outside of any methods (b in the above example)

La bla bla
  • 8,558
  • 13
  • 60
  • 109
  • As written, that's not true. I access non-final variables from the enclosing class all the time, in cases just like this: an ActionListener updating values in controls. Maybe there's a piece you've left out that would make this statement true. – Jay Jul 09 '12 at 21:37
  • Sorry, I miss wrote that. class variables, can be access (i.e members - private, public etc). local variable of the method containing the anonymous class, must be final. editing my answer – La bla bla Jul 09 '12 at 21:43
-1

You are getting that message because you have declared JLabel score to be final. You can't use a non-final variable to set a value for a final variable. I don't know why you want to make score final. Just remove that final.

Edit: I missed that correctScore is a function variable on my first reading. If you make it a class variable I think many of your problems will go away.

Jay
  • 26,876
  • 10
  • 61
  • 112