Reputation: 3815
From Java in a Nutshell, 2.10 Reference Types,
Java does not manipulate objects and arrays directly. Instead, it manipulates references to objects and arrays. Because Java handles objects and arrays by reference, classes and array types are known as reference types. In contrast, Java handles values of the primitive types directly, or by value.
But from the following, it appears that primitive wrapper classes (Objects) are actually handled by value rather than reference,
> Integer foo = new Integer(1);
> Integer bar = foo;
> bar = new Integer(2);
> foo
1
So is it true that the quote from above is not quite right?
UPDATE: My confusion came from misunderstanding the distinction between my code snippet above and something like the following:
> import java.util.LinkedList;
> LinkedList<Integer> foo = new LinkedList<Integer>();
> foo.add(1);
> LinkedList<Integer> bar = foo;
> bar.remove();
> System.out.println(foo.size());
0
> System.out.println(bar.size());
0
Where in this latter case, bar.remove()
actually operates on the LinkedList to which both foo
and bar
reference.
Upvotes: 0
Views: 1694
Reputation: 280181
What the quote you linked to is referring to is field access and array access expressions. Those need to go through a reference value to determine the underlying object.
The =
operator is known as the assignment operator. In your case, it's not a field access expression, nor an array access expression, so we fall to the third case
- First, the left-hand operand is evaluated to produce a variable. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason; the right-hand operand is not evaluated and no assignment occurs.
- Otherwise, the right-hand operand is evaluated. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.
- Otherwise, the value of the right-hand operand is converted to the type of the left-hand variable, is subjected to value set conversion (§5.1.13) to the appropriate standard value set (not an extended-exponent value set), and the result of the conversion is stored into the variable.
So in
bar = new Integer(2);
the bar
is evaluated and produces a variable, itself. Then, new Integer(2)
must be evaluated. That is a new instance creation expression. It produces an instance whose value is a reference value
The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object.
Once that value is generated, it is assigned to bar
.
Note how foo
was never involved.
Upvotes: 0
Reputation: 727077
Your code fragment does not demonstrate that the wrappers behave like value types: in fact, they are reference types, and they are immutable.
Integer foo = new Integer(1); // foo references an object wrapping 1
Integer bar = foo; // bar references the same object as foo
bar = new Integer(2); // bar references an object wrapping 2;
// continues to reference 1
A simple way to see what happens with primitive wrappers is to compare them for equality using ==
operator instead of calling equals
. You need to be careful to avoid comparing wrappers of small numbers, though, because they are cached for performance reasons.
Upvotes: 1
Reputation: 85799
Primitive class wrappers are object references, not primitive types.
In your example, you're assigning a new value to your variable, not updating the state. That's why foo
keeps its old value (old because it was never changed):
Integer foo = new Integer(1);
Integer bar = foo; //bar and foo "points" to the same location
bar = new Integer(2); //now bar only "points" to a new location, foo is unaffected
System.out.println(foo);
You can easily test this by using ==
and equals
comparison:
Integer a = 128;
Integer b = 128;
System.out.println(a == b); //false
System.out.println(a.equals(b)); //true
Upvotes: 1