简体   繁体   中英

Trouble understanding why I cannot modify variable outside a method?

public class test {

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

        final int num = 111;

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

    }
}

I want to change the value of num however I can only do that if I set it to final which would not let me modify this. In other languages such as C we can use pointers but Java cannot?

Java has neither closure nor pointers.

A solution would be to make the num static in the class :

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

Another solution would be to use an object like AtomicInteger . You can't change the value of the variable but you can change the content of the value :

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();
    }
}

Why this isn't allowed

main is a method. As with other programming languages, when a method returns, all of the variables declared in its body go out of scope, and accessing them has undefined behavior. Under some circumstances, the memory location where they used to be will no longer be valid.

Obviously this is a problem. If you try to change num after main has returned, you might overwrite a portion of the stack that doesn't belong to num anymore. Java's response to this difficult situation is to introduce restrictions on how you can share variables: they must be final. Java can then safely locate them in such a way that reading them will produce consistent results even after the function has returned.

The C equivalent to this problem is storing and using the address of a local variable outside of its scope, something that all C programmers are taught to never do.

To get around it, declare num as a member of test , create an instance, and pass that to it. This removes the dependancy on a local variable, and thus removes the final restriction.

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();
    }
}

Well, you can access it if you declare variable outside the function. Like this:

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();

    }
}

You are creating new Thread() { class as inner class. You can't access outer class variables without declaring them as final.

You can't change final variable references.

There are two ways you can do this,

1) Make num as static

2) Wrap num inside an object (You can update state of the object even though you define reference as final).

NOTE: Both are not thread safe.

Yep you can't win here! You need to set it final to be able to access it, but then you will not be able to modify it. You'll need to look at a different approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM