Reputation:
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?
Upvotes: 6
Views: 1466
Reputation: 280177
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;
Upvotes: 3
Reputation: 10893
You need to distinguish between a primitive and a referenced-object. Integer are not primitive 'per-se' but they have special properties due to 'boxing'. What you have is a primitive due to intValue() hence it gets the initial value (it has no more relation to the counter).
Well...for the record 'downgraders': the OP has changed his fields from 'int' to 'Integers' and therefore my initial answer was incorrect.
Upvotes: -2
Reputation: 3706
test
doesn't reference counter
. It has the same initial value. int
is a primitive.
Upvotes: 1
Reputation: 2353
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.
Upvotes: 3
Reputation: 140514
test
is not a pointer to counter
: you are setting its value to be equal to counter initially, but any subsequent changes to counter
will not be reflected in the value of test
.
If you want to have two references to the same mutable value, you can use something like AtomicInteger
:
static AtomicInteger counter = new AtomicInteger(0);
static AtomicInteger test = counter;
public static void main(String args[]) {
counter.incrementAndGet();
System.out.println("counter: " + counter);
System.out.println("test: " + test);
}
Output:
counter: 1
test: 1
Upvotes: 0