In today's lecture we look at what happens when you create an object.
Java's built-in primitive types lets the client represent integer and real numbers, but there is no primitive type that represents fractions. The ability to represent fractions might be useful when you need to write software for North American manufacturers, home builders, home owners, etc., where the US customary system of measurement (feet, inches, fractions of inches) is commonly used.
You could as the client keep track of all of the fraction numerators and denominators, but this quickly becomes cumbersome:
import java.io.PrintStream; public class YuckFractions { public static void main(String[] args) { PrintStream output = System.out; // computes Example 4.3 from the textbook manually int num1 = 5; int den1 = 3; int num2 = 7; int den2 = 6; int num3 = 31; int den3 = 45; int num4 = 3; int den4 = 4; // compute (num1 / den1) x (num2 / den2) int num5 = num1 * num2; int den5 = den1 * den2; // compute (num5 / den5) / (num3 / den3) int num6 = num5 * den3; int den6 = den5 * num3; // compute (num6 / den6) + (num4 / den4) int num7 = num6 * den4 + num4 * den6; int den7 = den6 * den4; output.printf("%d/%d%n", num7, den7); } }
type.lib.Fraction
The type.lib
package
provides a Fraction
class that encapsulates the idea of a fraction.
It provides methods for fraction arithmetic, getting and setting the
values of the numerator and denominator, and many other actions.
import java.io.PrintStream; import type.lib.Fraction; public class YippeeFractions { public static void main(String[] args) { PrintStream output = System.out; Fraction f = new Fraction(5, 3); f.multiply(new Fraction(7, 6)); f.divide(new Fraction(31, 45)); f.add(new Fraction(3, 4)); output.println(f); } }
int x;
Mean?Recall that the statement int x;
reserves
a block of memory large enough to hold an int
and labels the block with the identifier x
.
0 | ||
¦ | ||
main | ||
x ⇒ | 100 | |
104 | ||
¦ |
x = 17;
Mean?Recall that the statement x = 17;
stores
the value of 17
in the memory reserved for
the variable x
.
0 | ||
¦ | ||
main | ||
x ⇒ | 100 | 17 |
104 | ||
¦ |
Fraction f;
Mean?The statement Fraction f;
is similar to
the the statement int x;
. It causes a block
of memory to be reserved that is large enough to hold
what is called a reference to a
Fraction
object and labels the block with
the identifier f
.
0 | ||
¦ | ||
main | ||
f ⇒ | 100 | |
104 | ||
¦ |
Unlike the primitive types, the Java Language Specification does not say how much memory a reference occupies; here we have shown a 4 byte reference, but the size could be different depending on what virtual machine is being used.
We say that f
is a reference variable
that holds a value that refers to a Fraction
object (or a Fraction
instance). In this example, the
actual Fraction
object has not yet been created, so
no value is set for the memory block starting at 100
.
Fraction
ClassRecall that a class serves as a blueprint for creating objects;
the Fraction
class serves as a blueprint for creating
Fraction
objects.
The first time that the running program uses the Fraction
class, the compiled class is loaded somewhere into memory. In our
memory diagram model, the class is shown as a block of memory that
contains the attributes, methods, and constructors of the class.
Not all of the features need to shown in the memory diagram; in the
example below we only show the attributes that represent the
numerator and denominator:
0 | ||
¦ | ||
main | ||
f ⇒ | 100 | |
¦ | ||
¦ | ||
500 | Fraction class | |
numerator ⇒ | 504 | |
denominator ⇒ | 520 | |
¦ |
new Fraction(5, 3)
MeanThe expression new Fraction(5, 3)
creates a new Fraction
object with
a numerator of 5 and a denominator of 3. In our memory
diagram model, you can think of the expression as leading
to the following sequence of events:
Fraction
objectFraction
class into the allocated
block of memorynumerator
attribute
to 5
and the denominator
attribute to 3
.0 | ||
¦ | ||
main | ||
f ⇒ | 100 | |
¦ | ||
500 | Fraction class | |
numerator ⇒ | 504 | |
denominator ⇒ | 520 | |
¦ | ||
600 | Fraction object | |
numerator ⇒ | 604 | 5 |
denominator ⇒ | 620 | 3 |
¦ |
Notice that the class Fraction
is not used
to store the values of the numerator
or denominator
; the class (in this case) is
only used as a template to create the Fraction
object. The object is responsible for storing the values
of the numerator
and denominator
.
f = new Fraction(5, 3)
MeanThe statement f = new Fraction(5, 3)
causes a value to be stored in the memory reserved for the
variable f
. But what value is stored there?
Recall that f
is a reference variable; thus it
must hold some value that refers to an object in memory. We shall
use for the value the memory address
of the block of memory holding the newly created Fraction
object.
0 | ||
¦ | ||
main | ||
f ⇒ | 100 | 600 |
¦ | ||
500 | Fraction class | |
numerator ⇒ | 504 | |
denominator ⇒ | 520 | |
¦ | ||
600 | Fraction object | |
numerator ⇒ | 604 | 5 |
denominator ⇒ | 620 | 3 |
¦ |
Notice that the Fraction
object looks like a copy
of the Fraction
class; the object also has:
Whenever you declare a variable whose type is some sort of
object (i.e. not a primitive like int
or
double
) you are declaring a reference variable.
A reference variable holds a reference. A reference is some value that ultimately refers to an object in memory. In the preceding examples, we assumed that the reference was the memory address of an object.
The statement:
Fraction f = new Fraction(5, 3);
means f
is a variable whose value refers to a
Fraction
object.
f
IS NOT a Fraction
object.
f
IS NOT a Fraction
object.
f
IS NOT a Fraction
object.
one more time...
f
IS NOT a Fraction
object.
You can have multiple reference variables that all refer to the same object.
import java.io.PrintStream; import type.lib.Fraction; public class YippeeFractions2 { public static void main(String[] args) { PrintStream output = System.out; Fraction f = new Fraction(5, 3); Fraction g = f; f.multiply(new Fraction(7, 6)); f.divide(new Fraction(31, 45)); f.add(new Fraction(3, 4)); output.println(f); output.println(g); Fraction h = g; output.println(h); } }
In the above example, f
, g
, and
h
all refer to the same Fraction
object which results in the fraction 443/124
being printed 3 times.
Fraction g = f;
MeanThe statement Fraction g = f;
does
not create a new Fraction
object. Instead,
a block of memory is reserved to hold a reference to
a Fraction
object and the block is labelled
with the name g
. Then the value of
f
is copied into the memory block named
g
.
0 | ||
¦ | ||
main | ||
f ⇒ | 100 | 600 |
g ⇒ | 104 | 600 |
¦ | ||
500 | Fraction class | |
numerator ⇒ | 504 | |
denominator ⇒ | 520 | |
¦ | ||
600 | Fraction object | |
numerator ⇒ | 604 | 5 |
denominator ⇒ | 620 | 3 |
¦ |