One of my professor has given us a few practice questions for an exam, and one of the questions is something like the below (psuedocode):
a.setColor(blue);
b
The important thing to realize is, after the line a = b
, you don't have two objects anymore. You have two variables, both referring to the same object. So when you change that object's color, both variables reflect it. the line b = a
actually doesn't do anything.
Assuming you've already created two objects, and made variables a
and b
refer to them, you've initially got something like this.
a --> [ white ] b --> [ white ]
Your first two lines change the colours of the objects, to give you
a --> [ blue ] b --> [ red ]
Then, you point the variable a
to the object referred to by b
, so that they both refer to the same object. You now have
[ blue ] b --> [ red ] <-- a
Then you change the colour of the object referred to by b
.
[ blue ] b --> [ purple ] <-- a
Lastly, the line b=a;
does nothing, because b
already refers to the same object as a
.
It's because the fact that in first example, a
and b
are objects so this is what happens in each of the steps:
a <-- is an object
b <-- is an object
a.setColor(blue); <--
a
becomes blueb.setColor(red); <--
b
becomes reda = b; <-- IMPORTANT:: original
a
object is released and available for garbage collection and nowa
holds the reference ofb
object, which meana
andb
are referring the same object now, which isb
.b.setColor(purple); <-- b is purple now. Since a points to b only, a is also purple
Answer: Both a
and b
are purple at this point.
a
and b
are references to objects. When you write a=b
then a is assigned to the reference that was previously assigned to b
, so they now both reference the same object.
So, let's say you have two objects, O1 and O2, which at the beginning are assigned to a
and b
respectively.
a.setColor(blue); // the object O1 is set the color blue
b.setColor(red); // the object O2 is set the color red
a = b; // a now references O2, and b still references O2.
b.setColor(purple); // the object O2 is set the color purple.
b = a; // b is told to reference O2, which it already is.
If you want to think through the mind of C, you can see a
and b
as pointers, that can be exchanged between variables and whose data can be modified.
It's not the same for primitive values which are handled like they do in C.
Since everybody else has explained the difference between references and primitives I'll explain how this works under the surface.
So a reference to an object is essentially an number. Depending on the VM it will be either 32 bits or 64 bits, but it's still a number. This number tells you were in memory the object is. These numbers are called addresses and are usually written in hexadecimal base like so 0xYYYYYYYY
(this is an example of a 32 bit address, a 64 bit address would be twice as large).
Let's use your example from above using a 32 bit VM
a.setColor(blue); // Let's assume the object pointed to by a is at 0x00000001
b.setColor(red); // Let's assume the object pointed to by b is at 0x00000010
/* Now the following makes sense, what happens is the value of
a (0x00000001) is overwritten with 0x00000010.
This is just like you would expect if a and b were ints.
*/
a = b; // Both a and b have the value 0x00000010. They point to the same object
b.setColor(purple); // This changed the object stored at 0x00000010
b = a; // This says nothing because both a and b already contain the value 0x00000010
This should illustrate that references do work like numbers as you showed in your second example. However only under the surface, as far as you the programmer is concerned assignment of references don't work like assignment with primitives.
In Java you will never need to worry about the addresses of objects and the likes. In languages like C and C++ which enable lower level access this becomes more apparent and important.
Arithmetics? So can you do arithmetics and other stuff you can do with numbers? The shorter answer is no, not in java at least.
In C and C++ incrementing and decrementing pointers to objects is however perfectly valid and used a lot, for example to traverse arrays.
Feel free to ask questions if this wasn't clear enough.
In Java, it's generally correct to think of any variable which is an Object as being a pointer to a value of that Object type. Therefore, the following in Java:
Color a = new Color(), b = new Color();
a.setColor(blue);
b.setColor(red);
a = b;
b.setColor(purple);
b = a;
Should do more or less the same thing as the following in C++:
Color *a = new Color();
Color *b = new Color();
a->setColor(blue); // the value a points to is now blue
b->setColor(red); // the value b points to is now red
a = b; // a now points to the same value as b.
b->setColor(purple); // the value BOTH a and b point to is now purple
b = a; // this does nothing since a == b is already true
(Note that this is NOT the same as references - as per this article).
Also note that, for primitives, Java variables are simply values - NOT pointers. So, in the case of primitive integers, it should behave more or less as you expect in your question, since a = b
is setting the value of a
equal to the value of b
.