I always understood static variables to share one instance whenever they were referenced. I wanted to put this to the test but the results were different than I had expected.
static Integer counter = 0;
static Integer test = counter;
public static void main(String args[]) {
counter++;
System.out.println("counter: " + counter);
System.out.println("test: " + test);
}
output:
counter: 1
test: 0
Since test
references counter
I thought that when I increment counter
then test
will automatically be incremented as well. However, it seems test
is referencing 0
from somewhere, question is, where?
Since
test
referencescounter
This assumption is false. In Java, you cannot reference variables. What is stored in a variable is a value. That value can either be a primitive type value or a reference type value. In the case of primitives, the value is the value of the primitive. In the case of reference types,
In
int a = 0;
int b = a;
the variable a
is evaluated to produce a value, 0
, and that value is stored in b
.
In
Integer a = 0;
Integer b = a;
0
is converted to an Integer
through Integer.valueOf(int)
and the value, a reference to an Integer
object is stored in a
. Then a
is evaluated, producing the value of that reference to an Integer
object, and that value is stored in b
.
This is the same concept discussed in
Also, the fact that the variables are static
is irrelevant.
The only way around this is to update test
manually i.e.
counter++;
test = counter;
Here is my understanding.
Integer counter = 0;
what you're actually doing isInteger counter = new Integer(0);
Here you created an Integer object
whose value is 0 and counter
is reffering to it.Step 2: Integer test = counter;
Now test
is also referring to the same Integer object
we
created in step 1.
Step 3: Here comes the tricky part. When you do counter++;
in your main method, Java Auto-boxing and Auto-unboxing
features are implementing the below code for you.
counter = Integer.valueOf(counter.intValue() + 1);
As Integer
class is immutable in Java, when the value is incremented from 0 to 1, the valueOf()
method is creating a new Integer object
and storing the new value 1 in it instead of changing the old object's value (See below for Java's valueOf() method implementation). As you're referring the new object with counter
, it de-referenced the old Integer object
whose value is 0. But the reference variable test
is still holding the old Integer object
. This is the reason test
printing the old value.
Java's valueOf() method from library class Integer
638 public static Integer More ...valueOf(int i) {
639 assert IntegerCache.high >= 127;
640 if (i >= IntegerCache.low && i <= IntegerCache.high)
641 return IntegerCache.cache[i + (-IntegerCache.low)];
642 return new Integer(i); //See, new object is created here.
643 }
See below for detailed diagrammatic explanation.
Solid line implies reference variable is still holding the object.
Dotted line implies reference variable is no more holding the object.
test
doesn't reference counter
. It has the same initial value. int
is a primitive.
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