2012-07-09 57 views
0

可能重复:
Why are only final variables accessible in anonymous class?为什么在将ActionListener添加到按钮时突然需要将变量声明为“final”?

这是我对 “随机数学游戏” 的代码,我创建类:

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设置为最终时,它会导致各种其他错误。任何人都可以想出解决这个问题的方法吗?

+3

请参阅http://stackoverflow.com/a/4732617/597657 – 2012-07-09 21:33:19

回答

3

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

一种解决方法是addActionListener呼叫之前使用临时变量权:

final int temp = correctScore; 

,并使用该temp变量在actionPerformed方法。

请注意,当您这样做时,任何将来的更改correctScore将而不是都体现在temp的值中。

+0

这有帮助...谢谢。 – commandrix 2012-07-09 21:43:47

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在上面的例子)

+0

正如所写,这是不正确的。我总是访问封闭类中的非最终变量,如下所示:ActionListener更新控件中的值。也许有一件你遗漏了,这将使这个声明成真。 – Jay 2012-07-09 21:37:06

+0

对不起,我错过了。类变量,可以访问(即成员 - 私人,公共等)。包含匿名类的方法的局部变量必须是最终的。编辑我的答案 – 2012-07-09 21:43:05

-1

由于您已宣布JLabel评分为最终评分,因此您收到该消息。您不能使用非最终变量为最终变量设置值。我不知道你为什么想让比分最终。只要删除最后的。

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

相关问题