如何在内部嵌套方法中访问外部变量?

时间:2014-01-25 15:11:15

标签: java

我知道这个问题可能已经存在,这是我在网站上的第一个问题,所以请耐心等待。在我的案例中,我仍然很难理解这个问题。

所以事情就是这样:我有一个我调用的方法,我有一个可以改变x值的按钮。根据x的值,我希望程序做一些事情。下面的程序不是很完整,但你会明白这个想法:

public class foo{
        private void do(){
        int x=0;
        JButton changeValue= new JButton("Change the value of x");
        changeValue.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e){
                       x=10; //change the x value when the button is clicked
                             //Here the user may also change the value of x
                             //by inputting some other number
                 }
             });
        //Something happens depending on x
        //But nothing happens here because when I get the value of x,
        //it reverts back to 0.
        }
}

但是,无论我在do()中声明我的x,我都会收到一个错误,告诉我内部类不能访问外部类变量,并且必须将它们声明为final。但我无法宣布它是最终的,因为我需要稍后更改它。我已经尝试将值放在一个新类中。我也尝试将x声明为foo()的成员,但结果为x 为0或null因为某种原因一旦它退出按钮单击方法,它需要x返回其旧值:0或null。

我需要的是:当按下按钮时,x的值会改变(假设用户可以将x的值更改为其他数字)提前感谢您的任何答案。

2 个答案:

答案 0 :(得分:2)

您需要为final变量创建x引用。

由于它是原始类型,因此创建一个包装它的类:

private static class MyX {
    int x;
    // + getter and setter
}

然后:

final MyX myX = new MyX(x);
JButton changeValue= new JButton("Change the value of x");
changeValue.addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e){
        myX.setX(10);
    });
// get the value of MyX back if necessary

答案 1 :(得分:0)

问题是:当您创建ActionListener时,您声明将在稍后执行的actionPerformed。您无法从actionPerformed更改x,因为x仅存在于该方法调用中。

class Foo {
    void doSomething() {

        int x = 0; // x inside doSomething

        JButton btn = new Button("Do Something");

        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                /*
                 * This does not happen now:
                 * it happens later.
                 *
                 * By the time this happens
                 * the method will have exited
                 * and x will be gone.
                 *
                 */
            }
        });

        /* That x disappears forever here.
         * (Or a little bit later but basically here.)
         */
    }
}

您可以将x声明为final,然后为匿名类指定它的值,但您想要更改它。可能你想要的是把它变成一个领域:

class Foo {

    int x = 0; // x inside Foo

    JButton btn = new Button("Do Something");

    Foo() {
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                /* do something with x as needed */
            }
        });
    }
}

匿名类也可以包含字段:

btn.addActionListener(new ActionListener() {
    int x = 0; // x inside anonymous ActionListener

    @Override
    public void actionPerformed(ActionEvent ae) {
        /* use x only in actionPerformed */
    }
});

“我也尝试将x声明为foo()的成员,但结果是x为0或null,因为出于某种原因,一旦退出按钮单击方法,它需要x返回其旧值: 0或null。“

不幸的是,这可能意味着你做错了什么。我不确定你的描述和代码可能是什么。例如,您在一个看似不寻常的方法中在本地创建一个新的JButton。除非它是那些“createAndShowGUI”方法之一(如Swing tutorials所示),否则您可能会创建多个按钮,多个侦听器等。