Java错误:需要在actionPerformed中将变量声明为final,但我需要更改它

时间:2012-10-14 07:19:03

标签: java swing variables timer actionlistener

这已由Robin解决。谢谢罗宾!

我想做的事情背后的想法是制作一个每X秒执行一次动作的计时器,但X必须在不同的使用之间进行更改。

现在我这样做:

 try {
        final FileWriter fstream = new FileWriter("timetest.log");
        final BufferedWriter out = new BufferedWriter(fstream);

        ActionListener task_performer = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                critical_requests[0]++;
                try {
                    System.out.println("DEBUG: Critical Section requests: " + critical_requests[0] + "\n");
                    out.write("Critical Section request:\t" + critical_requests[0] + "\n");
                } catch (IOException e) {
                    System.out.println(e.getMessage() + "\n");
                }
                ((Timer)evt.getSource()).setDelay( 150 + (rand.nextInt(10) * time_unit ));
            }
        };
        new Timer(wait_delay, task_performer).start();
        System.out.println("Entering while loop\n");
        while(true) {
            if(critical_requests[0] >= 60){
                try {
                    out.close();
                } catch (IOException e) {
                    System.out.println("Close failed for some reason:\t" + e.getMessage() + "\n");
                    System.exit(-1);
                }
                System.exit(0);
            }
            //System.out.println("" + critical_requests[0] + "\n");    // Debug
            critical_requests[0] = critical_requests[0];    // Java is an insane language and it requires me to have this line here
        }
    } catch (IOException e) {
                System.out.println(e.getMessage());
                System.exit(-1);
    }

我得到的错误是:

local variable is accessed from within inner class; needs to be declared final

我尝试将其中一些作为最终版,但后来我无法更改侦听器内部的值。另外一些变量没有意义做出最终决定(BufferedWriter out,rand)。

所有5个编译器错误都是:     从内部类中访问局部变量rand;需要宣布最终 一个用于out,rand和wait_delay,另外两个用于critical_requests。

我如何协调这个?

3 个答案:

答案 0 :(得分:2)

查看代码的问题是wait_delaycritical_requests变量。

  1. 没有必要在ActionListener内更改它。在对Timer
  2. 的延迟产生任何影响之前,您必须再次在Timer上进行设置
  3. 每次更改Timer变量时都会创建一个新的wait_delay对象,这会导致很多Timer个实例,默认情况下每个实例都会重复Timer次重复。只有你打电话给setRepeats( false )他们才会真正停止。查看您的评论(应该是问题的一部分),您想要更新Timer
  4. 的延迟
  5. 如果您真的需要更改critical_requests中的ActionListener变量,可以将其存储在最终数组中
  6. 所以我建议将代码更改为

    final int[] critical_requests = new int[]{ 0 };
    final Outputstream out = ...;
    ActionListener task_performer = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                critical_requests[0] = critical_requests[0] + 1;
                try {
                    out.write("Critical Section request:\t" + (critical_requests[0]) + "\n");
                    ((Timer)evt.getSource()).setDelay( 10 + (rand.nextInt() % 10) );
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                    System.exit(-1);
                }
            }
    };
    Timer the_one_and_only_timer = new Timer( wait_delay, task_performer );
    

答案 1 :(得分:1)

通常,您有两种选择:

  • 将其设为类字段。
  • 使用另一个变量并为其分配旧变量,例如:

ActionListener task_performer = new ActionListener()
{
    public void actionPerformed(ActionEvent evt)
    {
        int temp = wait_delay; // assuming wait_delay is final
        temp = ...;

答案 2 :(得分:1)

在方法中使“wait_delay”非局部变量。把它从方法定义中删除。