(Just to be clear, the explanation I'm giving here is specific to Java and C#. Don't assume it applies to other languages, although bits of it may.)
I like to use an analogy of telling someone where I live. I might write my address on a piece of paper:
- A variable is like a piece of paper. It holds a value, but it isn't the value in itself. You can cross out whatever's there and write something else instead.
- The address that I write on the piece of paper is like a reference. It isn't my house, but it's a way of navigating to my house.
- My house itself is like an object. I can give out multiple references to the same object, but there's only one object.
Does that help?
The difference between a value type and a reference type is what gets written on the piece of paper. For example, here:
int x = 12;
is like having a piece of paper with the number 12 written on it directly. Whereas:
Dog myDog = new Dog();
doesn't write the Dog object contents itself on the piece of paper - it creates a new Dog
, and then writes a reference to the dog on that paper.
In non-analogy terms:
- A variable represents a storage location in memory. It has a name by which you can refer to it at compile time, and at execution time it has a value, which will always be compatible with its compile-time type. (For example, if you've got a
Button
variable, the value will always be a reference to an object of type Button
or some subclass - or the null
reference.)
- An object is a sort of separate entity. Importantly, the value of a variable or any expression is never an object, only a reference. An object effectively consists of:
- Fields (the state)
- A type reference (can never change through the lifetime of the object)
- A monitor (for synchronization)
- A reference is a value used to access an object - e.g. to call methods on it, access fields etc. You typically navigate the reference with the
.
operator. For example, if foo
is a Person
variable, foo.getAddress().getLength()
would take the value of foo
(a reference) and call getAddress()
on the object that that reference refers to. The result might be a String
reference... we then call getLength()
on the object that that reference refers to.