不能引用非final变量和Timer

时间:2012-05-14 16:25:13

标签: java timer anonymous-class

我正在尝试编写一个可以改变控件背景的静态类,它将被传递给参数。所以我实现了这个目标:

public static void wrong(final Component component) {

        component.setBackground(Color.RED);
        Timer   timer = new Timer(2, wrongAction);

        wrongAction = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                int green = component.getBackground().getGreen();
                int blue = component.getBackground().getBlue();
                component.setBackground(new Color(255, green + 1, blue + 1));
                if (component.getBackground() == Color.WHITE) {
                    timer.stop();
                }
            }
        };

        timer.start();

    }  

我有一个错误:

Cannot refer to a non-final variable timer inside an inner class defined in a different method

当然,我们可以将计时器更改为最终计时器,但是在我们这样做之后方法停止工作 我试图谷歌它并在其他stackoverflow主题中找到答案,但没有任何帮助我。

提前感谢大家!

4 个答案:

答案 0 :(得分:4)

问题是您使用了不同的wrongAction引用。

public static void wrong(final Component component) {

    component.setBackground(Color.RED);
    Timer   timer = new Timer(2, wrongAction);// <-- Here wrongAction is not the one you
                                              // define on the next line

    wrongAction = new ActionListener() { // <-- This is a new ActionListener but Timer
                                         // has no knowledge about it.
        @Override
        public void actionPerformed(ActionEvent e) {

            int green = component.getBackground().getGreen();
            int blue = component.getBackground().getBlue();
            component.setBackground(new Color(255, green + 1, blue + 1));
            if (component.getBackground() == Color.WHITE) {
                timer.stop();
            }
        }
    };

    timer.start();

}

以下代码将立即起作用(但我发现它不是很干净,最好将所有这些封装在一个专用对象中,这样Timer可以是类的变量,监听器可以引用它) :

public static void wrong(final Component component) {
        class MyActionListener implements ActionListener {
            private Timer timer;

            public void setTimer(Timer timer) {
                this.timer = timer;
            }

            @Override
            public void actionPerformed(ActionEvent e) {

                int green = component.getBackground().getGreen();
                int blue = component.getBackground().getBlue();
                component.setBackground(new Color(255, green + 1, blue + 1));
                if (component.getBackground().equals(Color.WHITE)) {
                    if (timer == null) {
                        System.err.println("This sucks, I got no timer");
                    } else {
                        timer.stop();
                    }
                }

            }
        }
        MyActionListener wrongAction = new MyActionListener();
        component.setBackground(Color.RED);
        Timer timer = new Timer(2, wrongAction);
        wrongAction.setTimer(timer);


        timer.start();

    }

答案 1 :(得分:1)

wrongAction是一个内部类,Java要求局部变量定义外部需要是最终的,以便在内部类中使用它:

final Timer   timer = new Timer(2, wrongAction);

wrongAction = new ActionListener() {
    //...
}

答案 2 :(得分:1)

你似乎将wrongAction传递给timer构造函数,然后实际初始化它!!!

不应该是代码

wrongAction = new ActionListener() {...
        };

高于

Timer   timer = new Timer(2, wrongAction);

???

当然,你需要Timer timer = null;在顶部

EDITED: 如何完全删除wrongAction并保持简单 -

final Timer   timer = new Timer(2, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                int green = component.getBackground().getGreen();
                int blue = component.getBackground().getBlue();
                component.setBackground(new Color(255, green + 1, blue + 1));
                if (component.getBackground() == Color.WHITE) {
                    timer.stop();
                }
            }
        });

答案 3 :(得分:0)

您可以在构造函数中传递null,然后添加ActionListener

final Timer timer = new Timer(2,null);

timer.addActionListener(new ActionListener(){
//...
});
timer.start();