麻烦理解为什么我不能修改方法外的变量?

时间:2012-10-18 14:34:04

标签: java scope

public class test {

    public static void main(String[] args) throws Exception {

        final int num = 111;

        new Thread() {
            @Override
            public void run() {
                num = 222;
            }
        }.start();

    }
}

我想更改num的值,但是如果我将其设置为final,我只能这样做,这不会让我修改它。在其他语言如C中,我们可以使用指针,但Java不能?

5 个答案:

答案 0 :(得分:3)

Java既没有封闭也没有指针。

解决方案是在类中使num静态:

public class test {
    static int num = 111;
    public static void main(String[] args) throws Exception {
        new Thread() {
            @Override
            public void run() {
                num = 222;
            }
        }.start();
    }
}

另一种解决方案是使用像AtomicInteger这样的对象。您无法更改变量的值,但可以更改值的内容:

public class test {
    public static void main(String[] args) throws Exception {
        final AtomicInteger num = new AtomicInteger(111);
        new Thread() {
            @Override
            public void run() {
                num.set(222);
            }
        }.start();
    }
}

答案 1 :(得分:2)

为什么不允许这样做

main是一种方法。与其他编程语言一样,当方法返回时,其主体中声明的所有变量都超出范围,并且访问它们具有未定义的行为。在某些情况下,以前的内存位置将不再有效。

显然这是一个问题。如果您在num返回后尝试更改main,则可能会覆盖不属于num的堆栈部分。 Java对这种困难情况的回应是对如何共享变量进行限制:它们必须是最终的。然后,Java可以安全地定位它们,即使在函数返回后,读取它们也会产生一致的结果。

与此问题相当的C是存储和使用其范围之外的局部变量的地址,这是所有C程序员都不会做的事情。

要解决此问题,请将num声明为test的成员,创建一个实例,并将其传递给它。这将删除局部变量的依赖性,从而删除final限制。

public class test
{
    int num = 111;

    public static void main(String[] args) throws Exception
    {
        test t = new test();
        (new Thread(t) {
            test mytest;
            Thread(test t)
            {
                mytest = t;
            }

            @Override
            public void run() {
                mytest.num = 222;
            }
        }).start();
    }
}

答案 2 :(得分:2)

好吧,如果在函数外部声明变量,则可以访问它。像这样:

public class test {

private static int num = 111;

    public static void main(String[] args) throws Exception {

        new Thread() {
            @Override
            public void run() {
                num = 222;
            }
        }.start();

    }
}

答案 3 :(得分:1)

您正在创建new Thread() {类作为内部类。如果不将它们声明为最终变量,则无法访问外部类变量。

您无法更改最终变量引用。

有两种方法可以做到这一点,

1)将num设为静态

2)在对象中包装num(即使您将引用定义为final,也可以更新对象的状态)。

注意:两者都不是线程安全的。

答案 4 :(得分:-1)

是的,你不能在这里赢!您需要将其设置为最终才能访问它,但之后您将无法对其进行修改。你需要看一个不同的方法。