Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inner Classes in Java

Tags:

java

I am making a keyboard-like buttons for my Hangman game (SEE PICTURE HERE), my problem is about the inner classes. I've read this LINK about inner classes and it says that you can only access the outside variables with FINAL type. But if I declared the variable as such, I cannot change the value of it anymore... So my problem is that I need to change the value inside the inner class. My code is as follows:

public class MainGame extends JDialog {

    private String player;
    private char [] wordChar;
    private JButton[] buttons;
    private int level;
    private int score;
    private int livesLeft;
    private int missedGuess;

 void newGame() {

        level = 0;
        score = 0;
        livesLeft = 10;
        missedGuess = 0;

       //label1:
       // while (livesLeft!= 0) {

            //get random WORD from LIST
            Word hiddenWord = new Word();

            //put random word in Array
            wordChar = new char[hiddenWord.getHiddenWord().length()];
            wordChar = hiddenWord.getHiddenWord().toCharArray();

            buttons = new JButton[wordChar.length];
            for (int i = 0; i < wordChar.length; i++){
                JButton guessWord = new JButton(" ");
                guessWord.setFont(new Font("Microsoft Sans Serif", 1, 18));
                guessWord.setEnabled(false);

                jPanel3.setLayout(new GridLayout(1, wordChar.length));
                jPanel3.add(guessWord);

                buttons[i] = guessWord;
            }
      checkLetter();
      }

    void checkLetter() {
         int checker = 0;
         while(checker != wordChar.length){
            jPanel1.setLayout(new GridLayout(3, 9, 3, 5));
            for (char buttonChar = 'a'; buttonChar <= 'z'; buttonChar++) {
                String buttonText = String.valueOf(buttonChar);
                final JButton letterButton = new JButton(buttonText);
                letterButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        String actionCommand = e.getActionCommand();
                        for (int j = 0; j < wordChar.length; j++){
                            String text =  String.valueOf(wordChar[j]);
                            if(actionCommand.equals(text)){
                                buttons[j].setText(text);
                                checker++; //THIS CODE IS NOT POSSIBLE!!!!
                            }
                        }
                    }
                });
                jPanel1.add(letterButton);
             }
               checker++;
          }
        }

NOTE: The code above is not complete. The int checker is used to count how many correct letters are already guessed so that if it is equal to the length of the word, I can now proceed to the next levelenter image description here

How can I re-do my code?

like image 434
newbie Avatar asked Jan 30 '11 13:01

newbie


2 Answers

You can declare checker as a field of outer class, and access it with some method, something like increaseChecker().

UPDATE: Something like this:

1) Create checker field in outer class:

public class OuterClassName {
    private int checker;

    protected void increaseChecker() {
        checker++;
    }

    void checkLetter() {
        // ...
    }

}

2) Use increaseChecker() method call instead of checker++

like image 108
Kel Avatar answered Nov 01 '22 17:11

Kel


You can't access local variables in an anonymous inner class, and that's for a good reason. The actionPerformed() method isn't guaranteed to be called inside the checkLetter() function. It will be called later, possibly (and most probably) after the function exits so its local variables will be destroyed by that time. Therefore, the newly created anonymous class implicitly gets a copy of that variable. But it wouldn't make any sense to increase the copy, that's why only final local variables can be accessed from methods of an anonymous class.

The simplest workaround is just to make checker a field of the outer class. But that wouldn't make any sense if it's accessed only within the checkLetter() function unless it is necessary for it to retain its value between checkLetter() calls. In order to find out the true answer, you need to think why you are trying to increase checker inside actionPerformed()? When should it happen and what are you trying to achieve by doing it?

like image 43
Sergei Tachenov Avatar answered Nov 01 '22 17:11

Sergei Tachenov