In the following code, why can't I see the variable "i" from another thread?
public class Main { public static void main(String[] args) { int i = 0; new Thread(new Runnable() { @Override public void run() { System.out.println(i); } }).start(); } }
And why can I see it in the code below?
public class Main { int i = 0; public static void main(String[] args) { new Main().method(); } private void method() { new Thread(new Runnable() { @Override public void run() { i = 1; } }).start(); } }
1) Any variable declared in a method is only visible in that method. (method-local). The programmer has no choice in that. 2) Any variable declared with the modifier private is visible only from within instances of the class it is delared in. 3) public variables can be accessed from any class with object.
Visibility of a variable is defined as if a variable is accessible or not inside a particular region of code or the whole program.
By default, the variables and methods of a class are accessible to members of the class itself and to other classes in the same package. To borrow from C++ terminology, classes in the same package are friendly. We'll call this the default level of visibility.
Java provides four types of access modifiers or visibility specifiers i.e. default, public, private, and protected.
From docs:
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields.
Now taking the second example first, when i
is declared in parent class, the inner class can access it, because inner class has access to entire parent object. And i
is correctly referenced as Main.this.i
from inner class.Now compiler secretly makes a copy of this.i
inside inner class. this
never changes inside the object, this.i
will point to correct object for both inner and outer class. Compiler is happy.
In first example, i
is not part of parent class, its declared inside a method hence its reference is now on stack, and not on heap. (In this case, i
doesn't get to live on that big outer circle shown in above diagram). Now compiler must secretly make a copy of i
inside inner class as well. But it is afraid that method's i
may change on stack. Compiler can't use outer class connection to get to i
here, and it can't bother to copy i
reference from stack every time it changes. So, it is decided that you must make the method's i
reference unchangeable, or in other words, final
.
The obscure secret tricks Java plays so that you can access outer fields from inner classes is explained in detail here: http://techtracer.com/2008/04/14/mystery-of-accessibility-in-local-inner-classes/
and discussed more "why's" here : http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg04044.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With