|
JavaFAQ Home » Java Lectures by Anatoliy Malyarenko

The life cycle of an object
by: Anatoliy Malyarenko
Abstract
- Contents of the lecture.
- Creating objects.
- Using objects.
- Cleaning up unused objects.
- Summary of creating and using objects.
Objects
A typical Java program creates many objects, which interact with one another by sending
each other messages. Through these object interactions, a Java program can implement a
GUI, run an animation, or send and receive information over a network. Once an object has
completed the work for which it was created, it is garbage-collected and its resources are
recycled for use by other objects.
Here's a small program, called CreateObjectDemo, that creates three objects: one
Point object and two Rectangle objects. You will need all three source files to compile this
program.
| Code: |
public class CreateObjectDemo {
public static void main(String[] args) {
// create a point object and two rectangle objects
Point origin_one = new Point(23, 94);
Rectangle rect_one = new Rectangle(origin_one, 100, 200);
Rectangle rect_two = new Rectangle(50, 100);
// display rect_one’s width, height, and area
System.out.println("Width of rect_one: " +
rect_one.width);
System.out.println("Height of rect_one: " +
rect_one.height);
System.out.println("Area of rect_one: " +
rect_one.area());
// set rect_two’s position
rect_two.origin = origin_one;
// display rect_two’s position
System.out.println("X Position of rect_two: " +
rect_two.origin.x);
System.out.println("Y Position of rect_two: " +
rect_two.origin.y);
// move rect_two and display its new position
rect_two.move(40, 72);
System.out.println("X Position of rect_two: " +
rect_two.origin.x);
System.out.println("Y Position of rect_two: " +
rect_two.origin.y);
}
}
|
After creating the objects, the program manipulates the objects and displays some
information about them. Here's the output from the program:
Width of rect_one: 100
Height of rect_one: 200
Area of rect_one: 20000
X Position of rect_two: 23
Y Position of rect_two: 94
X Position of rect_two: 40
Y Position of rect_two: 72
Creating objects
As you know, a class provides the blueprint for objects; you create an object from a
class. Each of the following statements taken from the CreateObjectDemo program creates
an object:
| Code: |
Point origin_one = new Point(23, 94);
Rectangle rect_one = new Rectangle(origin_one, 100, 200);
Rectangle rect_two = new Rectangle(50, 100);
|
The first line creates an object from the Point class and the second and third lines each
create an object from the Rectangle class.
Each statement has three parts:
- Declaration. The code set in bold in the previous listing are all variable declarations that
associate a name with a type. When you create an object, you do not have to declare a
variable to refer to it. However, a variable declaration often appears on the same line as
the code to create an object.
- Instantiation. new is a Java operator that creates the new object (allocates space for it).
- Initialisation. The new operator is followed by a call to a constructor. For example,
Point(23, 94) is a call to Point's only constructor. The constructor initialises the new
object.
Declaring a variable to refer to an object
To declare a variable, you write:
type name
This notifies the compiler that you will use name to refer to data whose type is type.
In addition to the primitive types, such as int and boolean, provided directly by the Java
platform, classes and interfaces are also types. So to declare a variable to refer to an object,
you can use the name of a class or an interface, as the variable's type. The sample program
uses both the Point and the Rectangle class names as types to declare variables.
| Code: |
Point origin_one = new Point(23, 94);
Rectangle rect_one = new Rectangle(origin_one, 100, 200);
Rectangle rect_two = new Rectangle(50, 100);
|
Declarations do not create new objects. The code Point origin one does not create
a new Point object; it just declares a variable, named origin one, that will be used to refer
to a Point object. The reference is empty until assigned, as illustrated in the next figure. An
empty reference is known as a null reference.

To create an object you must instantiate it with the new operator.
Instantiating an object
The new operator instantiates a class by allocating memory for a new object. The
new operator requires a single, postfix argument: a call to a constructor. The name of the constructor provides the name of the class to instantiate. The constructor initialises the new object.
The new operator returns a reference to the object it created. Often, this reference is
assigned to a variable of the appropriate type. If the reference is not assigned to a variable, the
object is unreachable after the statement in which the new operator appears finishes executing.
Here's the code for the Point class:
| Code: |
public class Point {
public int x = 0;
public int y = 0;
//A constructor!
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
|
This class contains a single constructor. You can recognise a constructor because it has
the same name as the class and has no return type. The constructor in the Point class takes
two integer arguments, as declared by the code (int x, int y). The following statement
provides 23 and 94 as values for those arguments:
| Code: |
Point origin_one = new Point(23, 94);
|
The effect of the previous line of code can be illustrated in the next figure:

Here's the code for the Rectangle class, which contains four constructors:
| Code: |
public class Rectangle {
public int width = 0;
public int height = 0;
public Point origin;
//Four constructors
public Rectangle() {
origin = new Point(0, 0);
}
public Rectangle(Point p) {
origin = p;
}
public Rectangle(int w, int h) {
this(new Point(0, 0), w, h);
}
public Rectangle(Point p, int w, int h) {
origin = p;
width = w;
height = h;
}
//A method for moving the rectangle
public void move(int x, int y) {
origin.x = x;
origin.y = y;
}
//A method for computing the area
public int area() {
return width * height;
}
}
|
Each constructor lets you provide initial values for different aspects of the rectangle: the
origin; the width, and the height; all three; or none. If a class has multiple constructors, they
all have the same name but a different number of arguments or different typed arguments.
The Java platform differentiates the constructors, based on the number and the type of the
arguments.
When the Java platform encounters the following code, it knows to call the
constructor in the Rectangle class that requires a Point argument followed by two integer
arguments:
| Code: |
Rectangle rect_one = new Rectangle(origin_one, 100, 200);
|
This call initialises the rectangle's origin variable to the Point object referred to by
origin one. The code also sets width to 100 and height to 200. Now there are two references
to the same Point object; an object can have multiple references to it, as shown in the next
figure:

Multiple references can refer to the same object. The following line of code calls the
constructor that requires two integer arguments, which provide the initial values for width and
height. If you inspect the code within the constructor, you will see that it creates a new Point
object whose x and y values are initialised to 0:
| Code: |
Rectangle rect_two = new Rectangle(50, 100);
|
The Rectangle constructor used in the following statement doesn't take any arguments,
so it's called a no-argument constructor:
| Code: |
Rectangle rect = new Rectangle();
|
If a class does not explicitly declare any constructors, the Java platform automatically
provides a no-argument constructor, called the default constructor, that does nothing. Thus,
all classes have at least one constructor.
Using objects
Once you've created an object, you probably want to use it for something. You may need
information from it, want to change its state, or have it perform some action.
Objects give you two ways to do these things:
- Manipulate or inspect its variables.
- Call its methods.
Referencing an object's variables
The following is the general form of a qualified name, which is also known as a long
name:
objectReference.variableName
You may use a simple name for an instance variable when the instance variable is
in scope -- that is, within code for the object's class.
Code that is outside the object's
class must use a qualified name. For example, the code in the CreateObjectDemo class
is outside the code for the Rectangle class. So to refer to the origin, width, and height
variables within the Rectangle object named rect one, the CreateObjectDemo class must
use the names rect one.origin, rect one.width, and rect one.height, respectively.
The program uses two of these names to display the width and the height of rect one:
| Code: |
System.out.println("Width of rect_one: "
+ rect_one.width);
System.out.println("Height of rect_one: "
+ rect_one.height);
|
Attempting to use the simple names width and height from the code in the
CreateObjectDemo class doesn't make sense -- those variables exist only within an object --
and results in a compiler error.
Later, the program uses similar code to display information about rect two. Objects of
the same type have their own copy of the same instance variables. Thus, each Rectangle
object has variables named origin, width, and height. When you access an instance
variable through an object reference, you reference that particular object's variable. The two
objects rect one and rect two in the CreateObjectDemo program have different origin,
width, and height variables.
The first part of the variable's qualified name, objectReference, must be a reference
to an object. You can use the name of a reference variable here, as in the previous examples,
or you can use any expression that returns an object reference. Recall that the new operator
returns a reference to an object. So you could use the value returned from new to access a
new object's variables:
| Code: |
int height = new Rectangle().height;
|
This statement creates a new Rectangle object and immediately gets its height.
In essence, the statement calculates the default height of a Rectangle. Note that after
this statement has been executed, the program no longer has a reference to the created
Rectangle, because the program never stored the reference in a variable. The object is
unreferenced, and its resources can be recycled by the Java platform.
A word about variable access
The direct manipulation of an object's variables by other objects and classes is
discouraged because it's possible to set the variables to values that don't make sense. For
example, consider the Rectangle class from the previous section. Using that class, you can
create a rectangle whose width and height are negative, which, for some applications, doesn't
make sense.
Ideally, instead of allowing direct manipulation of variables, a class would provide
methods through which other objects can inspect or change variables. These methods ensure
that the values of the variables make sense for objects of that type. Thus, the Rectangle class
would provide methods called setWidth, setHeight, getWidth, and getHeight for setting
and getting the width and the height. The methods for setting the variables would report an
error if the caller tried to set the width or the height to a negative number. The other advantage
of using methods instead of direct variable access is that the class can change the type and
the names of the variables it uses for storing the width and the height without affecting its
clients.
However, in practical situations, it sometimes makes sense to allow direct access to an
object's variables. For example, both the Point class and the Rectangle class allow free
access to their member variables by declaring them public. This keeps these classes small
and simple. Also, it keeps them generally useful. Some applications might allow rectangles
with negative widths and heights.
The Java programming language provides an access control mechanism whereby
classes can determine what other classes can have direct access to its variables. A class
should protect variables against direct manipulation by other objects if those manipulations
could result in values that don't make sense for objects of that type. Changes to these variables
should be controlled by method calls. If a class grants access to its variables, you can assume
that you can inspect and change those variables without adverse effects.
Calling the object's methods
You also use qualified names to call an object's method. To form the qualified name of a
method, you append the method name to an object reference, with an intervening period (.).
Also, you provide, within enclosing parentheses, any arguments to the method. If the method
does not require any arguments, use empty parentheses.
objectReference.methodName(argumentList);
or
objectReference.methodName();
The Rectangle class has two methods: area to compute the rectangle's area and move
to change the rectangle's origin. Here's the CreateObjectDemo code that calls these two
methods:
| Code: |
System.out.println("Area of rect_one: "
+ rect_one.area());
...
rect_two.move(40, 72);
|
The first statement calls rect one's area method and displays the results. The second
line moves rect two because the move method assigns new values to the object's origin.x
and origin.y.
As with instance variables, objectReference must be a reference to an object. You can
use a variable name, but you also can use any expression that returns an object reference.
The new operator returns an object reference, so you can use the value returned from new to
call a new object's methods:
| Code: |
new Rectangle(100, 50).area()
|
The expression new Rectangle(100, 50) returns an object reference that refers to a
Rectangle object. As shown, you can use the dot notation to call the new Rectangle's area
method to compute the area of the new rectangle.
Some methods, such as area, return a value. For methods that return a value, you can
use the method call in expressions. You can assign the return value to a variable, use it to
make decisions, or control a loop. This code assigns the value returned by area to a variable:
| Code: |
int areaOfRectangle = new Rectangle(100, 50).area();
|
Remember, invoking a method on a particular object is the same as sending a message
to that object. In this case, the object that area is invoked on is the rectangle returned by the
constructor.
The methods in our Point and Rectangle classes are all declared public, so they are
accessible to any other class. Sometimes, a class needs to restrict access to its methods. For
example, a class might have a method that only subclasses are allowed to call. A class can
use the same mechanism to control access to its methods as it uses to control access to its
variables.
Cleaning up unused objects
Some object-oriented languages require that you keep track of all the objects you create
and that you explicitly destroy them when they are no longer needed. Managing memory
explicitly is tedious and error prone. The Java platform allows you to create as many objects
as you want (limited, of course, by what your system can handle), and you don't have to worry
about destroying them. The Java runtime environment deletes objects when it determines that
they are no longer being used. This process is called garbage collection.
An object is eligible for garbage collection when there are no more references to that
object. References that are held in a variable are usually dropped when the variable goes out
of scope. Or, you can explicitly drop an object reference by setting the variable to the special
value null. Remember that a program can have multiple references to the same object; all
references to an object must be dropped before the object is eligible for garbage collection.
The Java runtime environment has a garbage collector that periodically frees the
memory used by objects that are no longer referenced.
The garbage collector does its
job automatically, although, in some situations, you may want to run the garbage collection
explicitly by calling the gc method in the System class. For instance, you might want to run the
garbage collector after a section of code that creates a large amount of garbage or before a
section of code that needs a lot of memory.
Finalisation
Before an object gets garbage-collected, the garbage collector gives the object an
opportunity to clean up after itself through a call to the object's finalize method. This process
is known as finalisation.
Most programmers don't have to worry about implementing the finalize method. In
rare cases, however, a programmer might have to implement a finalize method to release
resources, such as native peers, that aren't under the control of the garbage collector.
The finalize method is a member of the Object class, which is the top of the Java
platform's class hierarchy and a superclass of all classes. A class can override the finalize
method to perform any finalisation necessary for objects of that type. If you override finalize,
your implementation of the method should call super.finalize as the last thing it does.
Summary of creating and using objects
You create an object from a class by using the new operator and a constructor. The new
operator returns a reference to the object that was created. You can assign the reference to a
variable or use it directly.
A class controls access to its instance variables and methods by using the Java
platform's access mechanism. Instance variables and methods that are accessible to code
outside of the class that they are declared in can be referred to by using a qualified name. The
qualified name of an instance variable looks like this:
objectReference.variableName
The qualified name of a method looks like this:
objectReference.methodName(argumentList)
or
objectReference.methodName()
The garbage collector automatically cleans up unused objects. An object is unused if
the program holds no more references to it. You can explicitly drop a reference by setting the
variable holding the reference to null.
by Anatoliy Malyarenko Printer Friendly Page
Send to a Friend
..
Search here again if you need more info!
|