Quote of the day
A soul without a high aim is like a ship without a rudder
Introduction to Classes
• When you define a class, you declare its exact form and nature. You do this by specifying the data that it
contains and the code that operates on that data. While very simple classes may contain only code or only
data, most real-world classes contain both. As you will see, a class’ code defines the interface to its data.
A class is declared by use of the class keyword. The classes that have been used up to this point are
actually very limited examples of its complete form. Classes can (and usually do) get much more complex.
• The data, or variables, defined within a class are called instance variables. The code is contained within
methods. Collectively, the methods and variables defined within a class are called members of the class.
In most classes, the instance variables are acted upon and accessed by the methods defined for that class.
Thus, it is the methods that determine how a class’ data can be used. Variables defined within a class are
called instance variables because each instance of the class (that is, each object of the class) contains its
own copy of these variables. Thus, the data for one object is separate and unique from the data for
another. We will come back to this point shortly, but it is an important concept to learn early.
• All methods have the same general form as main( ), which we have been using thus far. However, most
methods will not be specified as static or public. Notice that the general form of a class does not specify a
main( ) method. Java classes do not need to have a main( ) method. You only specify one if that class is
the starting point for your program. Further, applets don’t require a main( ) method at all.
A Simple Class
Let’s begin our study of the class with a simple example. Here is a class
called Box that defines three instance variables: width, height, and
depth. Currently, Box does not contain any methods.
class Box {
double width;
double height;
double depth;
}
• As stated, a class defines a new type of data. In this case, the new
data type is called Box. You will use this name to declare objects of
type Box. It is important to remember that a class declaration only
creates a template; it does not create an actual object. Thus, the
preceding code does not cause any objects of type Box to come into
existence.
To actually create a Box
object, you will use a
statement like the following:
Box mybox = new Box(); // create a Box object called mybox.
• After this statement executes, mybox will be an instance of Box. Thus,
it will have “physical” reality. For the moment, don’t worry about the
details of this statement. Again, each time you create an instance of a
class, you are creating an object that contains its own copy of each
instance variable defined by the class. Thus, every Box object will
contain its own copies of the instance variables width, height, and
depth. To access these variables, you will use the dot (.) operator. The
dot operator links the name of the object with the name of an
instance variable.
For example, to assign the
width variable of mybox the
value 100, you would use the
following statement:
mybox.width = 100;
• This statement tells the compiler to assign the copy of width that is
contained within the mybox object the value of 100. In general, you
use the dot operator to access both the instance variables and the
methods within an object.
DECLARING OBJECTS
• As just explained, when you create a class, you are creating a new data
type. You can use this type to declare objects of that type. However,
obtaining objects of a class is a two-step process. First, you must declare a
variable of the class type. This variable does not define an object. Instead, it
is simply a variable that can refer to an object. Second, you must acquire an
actual, physical copy of the object and assign it to that variable.
• You can do this using the new operator. The new operator dynamically
allocates (that is, allocates at run time) memory for an object and returns a
reference to it. This reference is, more or less, the address in memory of
the object allocated by new. This reference is then stored in the variable.
Thus, in Java, all class objects must be dynamically allocated.
• Let’s look at the details of this procedure. In the preceding sample programs,
a line similar to the following is used to declare an object of type Box:
• Box mybox = new Box();
• This statement combines the two steps just described. It can be rewritten
like this to show each step more clearly:
• Box mybox; // declare reference to object
• mybox = new Box(); // allocate a Box object
• The first line declares mybox as a reference to an object of type Box. After
this line executes, mybox contains the value null, which indicates that it
does not yet point to an actual object. Any attempt to use mybox at this
point will result in a compile-time error. The next line allocates an actual
object and assigns a reference to it to mybox. After the second line
executes, you can use mybox as if it were a Box object. But in reality, mybox
simply holds the memory address of the actual Box object.
• As just explained, the new operator dynamically allocates memory for an
object. It has this general form:
• class-var = new classname( );
• Here, class-var is a variable of the class type being created. The
classname is the name of the class that is being instantiated. The class
name followed by parentheses specifies the constructor for the class.
A constructor defines what occurs when an object of a class is
created. Constructors are an important part of all classes and have
many significant attributes. Most real-world classes explicitly define
their own constructors within their class definition. However, if no
explicit constructor is specified, then Java will automatically supply a
default constructor.
• This is the case with Box. For now, we will use the default constructor. Soon, you will see how to
define your own constructors. At this point, you might be wondering why you do not need to use
new for such things as integers or characters. The answer is that Java’s simple types are not
implemented as objects. Rather, they are implemented as “normal” variables. This is done in the
interest of efficiency. As you will see, objects have many features and attributes that require Java
to treat them differently than it treats the simple types. By not applying the same overhead to
the simple types that applies to objects, Java can implement the simple types more efficiently.
Later, you will see object versions of the simple types that are available for your use in those
situations in which complete objects of these types are needed. It is important to understand
that new allocates memory for an object during run time. The advantage of this approach is that
your program can create as many or as few objects as it needs during the execution of your
program. However, since memory is finite, it is possible that new will not be able to allocate
memory for an object because insufficient memory exists. If this happens, a run-time exception
will occur. For the sample programs in this book, you won’t need to worry about running out of
memory, but you will need to consider this possibility in real-world programs that you write.
• Let’s once again review the distinction between a class and an object.
A class creates a new data type that can be used to create objects.
That is, a class creates a logical framework that defines the
relationship between its members. When you declare an object of a
class, you are creating an instance of that class. Thus, a class is a
logical construct. An object has physical reality. (That is, an object
occupies space in memory.) It is important to keep this distinction
clearly in mind.
METHODS
• As mentioned at the beginning of this chapter, classes usually consist
of two things: instance variables and methods. The topic of methods
is a large one because Java gives them so much power and flexibility.
In fact, much of the next chapter is devoted to methods. However,
there are some fundamentals that you need to learn now so that you
can begin to add methods to your classes.
This is the general form of a
method:
type name(parameter-list) {
// body of method
}
• Here, type specifies the type of data returned by the method. This can be any valid type,
including class types that you create. If the method does not return a value, its return
type must be void. The name of the method is specified by name. This can be any legal
identifier other than those already used by other items within the current scope. The
parameter-list is a sequence of type and identifier pairs separated by commas.
Parameters are essentially variables that receive the value of the arguments passed to
the method when it is called. If the method has no parameters, then the parameter list
will be empty. Methods that have a return type other than void return a value to the
calling routine using the following form of the return statement:
• return value;
• Here, value is the value returned.
• In the next few sections, you will see how to create various types of methods, including
those that take parameters and those that return values.
Adding a Method to the Box Class
• Although it is perfectly fine to create a class that contains only data, it rarely
happens. Most of the time you will use methods to access the instance variables
defined by the class. In fact, methods define the interface to most classes.
• This allows the class implementer to hide the specific layout of internal data
structures behind cleaner method abstractions. In addition to defining methods
that provide access to data, you can also define methods that are used
internally by the class itself. Let’s begin by adding a method to the Box class. It
may have occurred to you while looking at the preceding programs that the
computation of a box’s volume was something that was best handled by the Box
class rather than the BoxDemo class. After all, since the volume of a box is
dependent upon the size of the box, it makes sense to have the Box class
compute it.
Look closely at the
following two lines of
code:
mybox1.volume();
mybox2.volume();
• The first line here invokes the volume( ) method on mybox1. That is, it
calls volume( ) relative to the mybox1 object, using the object’s name
followed by the dot operator.
• Thus, the call to mybox1.volume( ) displays the volume of the box
defined by mybox1, and the call to mybox2.volume( ) displays the
volume of the box defined by mybox2. Each time volume( ) is invoked,
it displays the volume for the specified box.
• If you are unfamiliar with the concept of calling a method, the following discussion will help
clear things up. When mybox1.volume( ) is executed, the Java run-time system transfers
control to the code defined inside volume( ). After the statements inside volume( ) have
executed, control is returned to the calling routine, and execution resumes with the line of
code following the call. In the most general sense, a method is Java’s way of implementing
subroutines. There is something very important to notice inside the volume( ) method: the
instance variables width, height, and depth are referred to directly, without preceding them
with an object name or the dot operator. When a method uses an instance variable that is
defined by its class, it does so directly, without explicit reference to an object and without
use of the dot operator. This is easy to understand if you think about it. A method is always
invoked relative to some object of its class. Once this invocation has occurred, the object is
known. Thus, within a method, there is no need to specify the object a second time. This
means that width, height, and depth inside volume( ) implicitly refer to the copies of those
variables found in the object that invokes volume( ).
• Let’s review: When an instance variable is accessed by code that is
not part of the class in which that instance variable is defined, it must
be done through an object, by use of the dot operator. However,
when an instance variable is accessed by code that is part of the same
class as the instance variable, that variable can be referred to directly.
The same thing applies to methods.