int value; //Declare an integer variable named value.
value=100; // Store the number 100 in value.
System.out.println(value); // Print the number in value, "100"
value=20; // Put 20 in value. Over-writes the 100.
count=value; // Gets the number from value and puts
// it in count.
// Assumes 'count' was declared as an int before.
When we use objects, we're using a more complex kind of variable. We don't do it for the sake of complexity, but because adding some complexity here makes things a lot simpler elsewhere in our program. A lot simpler.
Object variables are called "reference types", the type is actually the class that the object belongs to. The difference between a reference variable and a primitive variable is that a primitive variable actually is a storage location in computer memory that holds the stored information. A reference variable is a name that names a specific type of information. It doesn't actually hold the information, it's just associated with an object that actually holds the information.
This why there's a two step process in creating a Java variable. The first step, declaration, sets up a name we're going to use for a particular type of object. The second step, initialization, associates that name with an object--creating a new object if necessary.
Let's say I'm talking to a friend. I say, "I'm going to get a hamster and call it Wilmot."
"That's nice," says the friend. "Can I see Wilmot?"
"I don't have him yet."
"What color is Wilmot?"
"I don't know, I don't have a hamster yet."
Then I go to the pet store and pick up a hamster. I call him Wilmot, put him in a cage and take him home. I've now initialized the name Wilmot I declared to my friend earlier to point to a specific hamster.
Now when my friend says "Can I see Wilmot?" I can show him a hamster, and say "This is Wilmot." When he wants to know the color, there is an object to get the color of.
In Java terms, if I had a Hamster class, I could declare a name like this:
Hamster wilmot;
I now have a name for a Hamster object, but no Hamster. I can initialize the reference variable by getting a new Hamster object using the class's constructor, Hamster():
wilmot=new Hamster();
Now I have a Hamster object associated with the name. The name references the Hamster object that's been created. Hence the term "reference variable".
Now, if I create a new name and make it point to the same Hamster object, it becomes a new name for the same object:
Hamster fluffy;
fluffy=wilmot;
Now, if I make any changes to fluffy they also happen to wilmot. For example, if wilmot's size is 10cm, and I set fluffy's size to 12cm, then get wilmot's size it will be 12cm.
This is different from what happens with primitive variables. If I do the same thing with a pair of primitive variables like this:
int value, count;
value=100; // Initialize value to 100;
count=value; // Set count equal to value.
count=count-20; // Subtract 20 from count.
// We could have said 'count-=20;', too.
System.out.println("value= " + value); // Print value.
System.out.println("count= " + count); // Print count.
Then the output will be:
value= 100
count= 80
With a primitive variable, when we set it equal to another primitive we get a copy of the value in that primitive's own storage. When we set a reference variable equal to another reference variable, we are now referring to the same object as the other reference variable. In pet terms, it's like giving our hamster a second name. We might call it wilmot or fluffy, but they're both the same hamster.
If we need to have each name apply to a different hamster, we need to go back to the pet store for another hamster. In Java, we need to use the constructor to get another Hamster object:
Hamster wilmot, fluffy;
wilmot=new Hamster();
fluffy=wilmot; // fluffy and wilmot are now both names
// for the same Hamster object. Anything we do to fluffy
// will also apply to wilmot, and vice versa.
fluffy=new Hamster();
// Now fluffy applies to a different Hamster object.
// We can make changes to fluffy and
// they won't affect wilmot. We now have two
// Hamster objects, each with its own name
// to refer to it.
But what if we want it to act like a primitive object? What if we want a copy of wilmot to make changes to without affecting wilmot? Then we use a method of the object's class to create a new object that's a copy of that object. Usually this will be clone():
Hamster wilmot, fluffy;
wilmot=new Hamster();
fluffy=wilmot.clone();
Now fluffy is a copy of wilmot, and we can make changes to fluffy without affecting wilmot. Note: whether a class has the clone() method varies from class to class. Normally, if the class implements the Clonable interface then it has a clone() method that works this way.