1.3. Reference Type Examples¶
For the examples in this section, you should assume access to a class
called Person
(which defines the Person
reference type) that
has the following declaration:
public class Person {
// instance variables
private String name;
private int age;
// constructor
public Person(String name, int age) {
this.name = name;
this.age = age;
} // Person
// assume getter and setter methods exist...
} // Person
In Java, the reference types (§4.3) are class types, interface types, and array types. Of these three, you are likely familiar with declaring variables of both class and array types. Interfaces will be covered later in this course.
Below are two example declarations of reference type variables:
Person ada; // A class type variable (valid because we have a class called Person)
double[] array; // An array type variable
An object is really just a collection of variables and methods
that are defined by a class. It is not uncommon to describe Java
objects as dynamically constructed instances of a class. This
means that an object is constructed using the class as a blueprint
when the keyword new
is encountered (while the program is running).
When an object is constructed, its collection of variables is stored
contiguously in some location in memory. That location in memory (the
address) is what we call the object’s reference. In Java, the
possible values of a reference type are references to compatible
objects or null
.
Note
A reference variable either stores:
null
- when the varibles does not refer to an object.The location of an object in memory.
Below we describe various scenarios in which you may encounter/use reference variables in your code.
Example 1: Reference variable with a null
value
Consider the following declaration and initialization:
Person sue = null;
The variable sue
is of type Person
and null
is its
value. In Java, null
is a value that can always be assigned
to any reference type, and it is used to denote that the variable
does not currently refer to a valid object (so it does not have contain
a memory address). Therefore, we might say that variable sue
does
not currently refer to any object as the variable contains null
.
Under the Hood: Remember, sue
is an alias for some location
in the computer’s primary memory (RAM). Since using the
variable name is more readable and does not require us to
choose an arbitrary address, it is more common to diagram
this using the variable name. The diagram below
demonstrates this idea by showing the variable name (alias)
and its current value (null
).
Note
The diagram mentions main
because this code was run inside
of a main
method. The 5
next to main
denotes the
line number just after the code seen above. You can ignore the
line number in this example, but it will be useful in more
complex examples.
Example 2: Refer to Some Object
Now consider the following declaration/initialization:
Person sue;
sue = new Person("Sue", 19);
There are three important things that happen in this code, and it’s important to note that they happen in the following order:
the variable
sue
is declared withPerson
as its type;a new
Person
object is constructed; thenthe object’s reference (memory address) is assigned to
sue
.
Since the value of sue
is now a reference to some Person
object,
we say that sue
refers to the Person
object.
The memory diagram below shows the sue
variable, its value, and the the
Person
object that was created. The value of sue
is not the object
itself. That is why the Person
object is not in the box where you would
exect the value of sue
to be. Instead, it is a reference value that
indicates where that object is located in memory. This is why the
relationship between sue
and the object is depicted with an arrow and
why the the object itself appears elsewhere.
Important
Pay close attention to fact that variable sue
does not store the
object itself. Instead, sue
is the address where the Person
object resides in memory (12048
).
When a method is called using sue
(for example, sue.getName()
),
the object that sue
refers to is known as the calling
object. Non-static methods called using sue
are said to operate on
the calling object. Since the reference in the value of sue
can
change over time, the calling object can also change.
Test Yourself
Consider the following initializations:
Person sue = new Person("Sue", 19);
Person sally = sue;
Before moving on, take a moment to draw a diagram on a sheet of paper that shows how this looks under the hood (sometimes called a memory map or a memory diagram). Use the diagram above as an example. You can come up with arbitrary memory addresses as needed.
Do the best you can before looking at the solution!
Test Yourself Solution (Don’t open until completing the question above)
Your drawing should look very similar to the previous example with an
extra variable for sally
that contains the same value as the variable
sue
. We provide the diagram below.
The first line is the same as the previous example. On the second line, three things occur:
the variable
sally
is declared withPerson
as its type;the value of
sue
(a memory address) is retrieved by the computer; thenthe value is assigned to
sally
.
Since the value of sally
is now the same as the value of sue
, we
might say that sue
and sally
both refer to the same Person
object.
This is an interesting scenario because the calling object for sue
and
the calling object for sally
now refer to the same object!
Test Yourself
Consider the following code:
Person joe = new Person("Joe", 37);
Person chris = joe;
chris.setName("Chris"); // assume the setName method exists and changes the name of the calling object.
System.out.println(joe.getName());
Take a moment to draw the memory map diagram for the code above. If a line of code changes an instance variable, make sure your diagram reflects that change. Then, write the output from the program in your notes.
Do the best you can before looking at the solution!
Solution (Don’t open until completing the question above)
The first two lines of code are similar to the previous question (with the names changed). After line 2 executes, our diagram would look like this:
When we execute line 3 (chris.setName("Chris")
), we are
changing the our calling object chris
. Our
updated diagram should look like this:
When we execute line 4 (System.out.println(joe.getName());
),
the object referred to by variable joe
now has chris
set
as its name. So, our output will be Chris.
Rapid Fire Review
What is stored in a reference variable in Java?
The actual object.
The memory address where the object is stored.
The class type of the object.
The size of the object in memory.
In the following declaration, what does the variable
s
store?Scanner s = null;
A reference to an object of type
Scanner
.The value
null
, indicating thats
does not refer to any object.The specific memory location
800
.The
Scanner
class.
Given the following code, what happens when the second line executes?
Scanner s; s = new Scanner(System.in);
A new
Scanner
object is created, and its reference is assigned tos
.The value
null
is assigned tos
.The
Scanner
object is destroyed.The value of
s
is set to an arbitrary memory address.
The memory diagram below shows the relationship between
s
and aScanner
object in a program. The0
value that is shown is a placeholder forSystem.in
. What does the line froms
to theScanner
object represent?The actual
Scanner
object.The method that
s
calls.The reference stored in
s
that points to theScanner
object.The size of the
Scanner
object in memory.