Class Information

Defining a Class

You can define your own types by using the keyword class.

NOTE
The keyword class is the only way Java provides for you to create a new type. Java has no equivalent to typedef, struct, or enum (enumerated types).

A user type definition takes the following form:

class CMyClass
{
 // the members of the class go here
}


The class keyword is followed by the class name. The class name must be a valid Java identifier. (The same naming rules apply for classes as for variable names, as described in the section "Identifiers"). The members of the class can appear in any order within the class body.

There are two types of members to a class: data members and member functions.

Defining data members

Data members are used to describe the data properties of the class. Data members are declared using the same rules as local variables.

Defining member functions

Members of a Java class can also be functions. Member functions in Java are commonly known as methods of the class, or simply as methods.

NOTE
All functions in Java are methods.

A method definition consists of the following:

NOTE
A separate definition and declaration of a method isn't supported as it is in C++. In addition, defining a method within the class doesn't imply that the method is an inline function, and the inline keyword isn't supported in Java. The decision to expand a method inline is left to the compiler.

When a method is called, control passes to the open brace of the method. You can have the code exit from any point by using the keyword return. In the absence of encountering a return statement, the method exits upon reaching the closed brace. If the method returns something other than void, then a return statement, followed by an expression indicating the value to return, is required.

The following example declares a TV class containing a channel data member, and a tune() method that changes the channel:

/**
 * Represents a color television.
 */
class TV
{
 int channel;
 /**
 * Change the channel of the television.
 */
 void tune(int newChannel)
 {
 channel = newChannel;
 }
}


The Javadoc comments add the documentation for the TV class and the tune() method to the statement completion. (The Javadoc comments are not included in subsequent examples, to save space.)

Scope

By default, members of a class are not accessible from classes that are outside of the class's own domain. Attaching the keyword public makes members available from all classes.

Overloading methods

Java differentiates methods from each other by more than just their name. A method's fully qualified name includes its name, its class, and its arguments. Two methods can have the same name, as long as their fully qualified names are different. This is called function overloading (not to be confused with method overriding, which we'll discuss later).

Even though you have a tune() method in the class TV, you can still have a separate method tune() in the class Radio.

Within a class, two methods can have the same name as long as they can be discriminated between on the basis of their arguments. In a given class Bank, you could have a method int tune() that returns the current channel, and a method tune(int) that retunes the TV.

Objects

People sometimes get fast and loose with the terms "class" and "object." A class describes a type of thing. The class TV might be used to represent TVs. (Sometimes people use the terms "class" and "type" interchangeably—that's okay.) On the other hand, myTV refers to the TV object sitting in my living room. In this case, you can also say that myTV is an instance of TV.

References to objects

Java programs access objects by means of a reference. The following example declares two references:

TV myTV = new TV();
TV yourTV;
yourTV = myTV;


The first declaration creates a reference myTV to an object of class TV. The memory for that object comes from a pool of available memory known as the heap. The second declaration creates a reference yourTV, which points to nothing (technically, it points to the null object). After the assignment, yourTV and myTV point to the same TV object.

Members of the class TV are accessed through reference. The following demonstrates the principle:

class TV
{
 int channel;
 void tune(int newChannel)
 {
 channel = newChannel;
 }
}
class LivingRoom
{
 TV tv = new TV();
 void tuneTV(int channel)
 {
 tv.channel = channel;
 tv.tune(channel);
 }
}


The two references to the members of tv in the tuneTV() method have the same effect—one accesses the data member channel directly, while the other uses the access method tune() to change the channel. Since numerous internal steps can be required to tune a TV other than simply changing the channel variable, it's preferable to use the access method.

What is this?

Notice that the reference to channel within the TV tune() method isn't qualified to any particular object. The tune() methods set the channel variable of whichever object it's called with.

TV myTV = new TV();
TV sonsTV = new TV();
myTV.tune(HISTORY_CHANNEL);
sonsTV.tune(MTV);


The first call tunes myTV to HISTORY_CHANNEL, while the second call tunes my sonsTV to MTV. (HISTORY_CHANNEL and MTV are both constants defined somewhere else).

A reference to a class member from within a method in the same class refers to the current object. A reference to the current object is called this.

Garbage collection

Objects to which there is no longer a reference can't be accessed. The memory for such lost objects is recovered by a background task known as the garbage collector. For example:

TV myTV = new TV();
TV sonsTV = new TV();
myTV = sonsTV;


By assigning sonsTV to myTV, the object originally referenced by myTV is lost. It will eventually be returned to the heap.

Static members of a class

Members of a class can be declared independently.

class TV
{
 static int numberOfTVs
}


The static data member numberOfTVs is shared by all objects of the class TV. Static members can be accessed by means of the class name TV.numberOfTVs or an object name myTV.numberOfTVs.

Since static members belong to the class TV and not any particular TV object, static methods have no this reference.

constructor

A special method that is invoked automatically whenever a class object is created is called a constructor. Its job is to initialize the object to a valid starting state. The constructor method carries the name of the class and has no return type.

class TV
{
 int channel;
 TV(int initialChannel)
 {
 channel = initialChannel;
 }
}
class LivingRoom
{
 TV myTV = new TV(HISTORY_CHANNEL);
}


The declaration within LivingRoom creates a TV object initially tuned to HISTORY_CHANNEL.

Class Inheritance

One class can inherit the properties of another class. For example, a ColorTV class might inherit many of the properties of a generic TV class—each of these classes could have a channel property as well as a tune() method. The ColorTV class could have extra properties as well, such as hue and colorIntensity.

Inheritance in Java

One class inherits from another class using the extends keyword. In practice, this appears as follows:

class ColorTV extends TV
{
 int color;
 /**
 * Set the color property.
 * @param r - the red component of the color (0-255)
 * @param g - the green component of the color (0-255)
 * @param b - the blue component of the color (0-255)
 */
 void setColor(r, g, b)
 {
 color = new Color(r, g, b);
 }
}


In this example, the class ColorTV extends the base class TV by adding the color property and the setColor() method. The ColorTV class inherits the channel property and the tune() method.

Note that even though ColorTV extends the TV class, a ColorTV object is a TV object. A ColorTV object can be used anywhere a TV object is called for.

NOTE
The @param directive defines the meaning of the method arguments to the statement completion feature.

Overriding base class methods

A subclass can override a method in the base class. For example, the class TV can define a method selfAdjust(), which adjusts the TV according to default values. Since this method doesn't include color, the class ColorTV would define its own class selfAdjust(). The ColorTV.selfAdjust() method overrides the TV.selfAdjust() method.

Consider the following method:

void someFunction(TV tv)
{
 tv.selfAdjust();
}


The call to selfAdjust() is dependent upon the exact type of tv. If tv is an object of class TV, the method TV.selfAdjust() is invoked, but if tv is actually of class ColorTV, ColorTV.selfAdjust() is invoked instead.

Invoking methods in the base class

Notice in the previous example that ColorTV.selfAdjust() might not completely replace the functions in TV.selfAdjust(); it might merely add extra properties related to color. It's possible for the method ColorTV.selfAdjust() to invoke the TV.selfAdjust() method as follows:

class ColorTV extends TV
{
 /**
 * Set properties to their default values.
 */
 void selfAdjust()
 {
 // invoke selfAdjust() in the base class
 super.selfAdjust();
 .
 .
 .
 }
}


The keyword super is the same as this, but it is of the same class as the base class.

Abstract classes

An abstract class is a class that can't be instantiated with an object. For example, there is no tv object that is actually of type TV. Perhaps all TV objects must be members of the class BWTV, ColorTV, or HDTV. In this case, the TV class is abstract and can't be instantiated with an object.

In the same sense, an abstract method is one that you can't define except in one of the base classes. For example, tune() would be an abstract method if the BWTV, ColorTV, and HDTV objects were all tuned differently. An abstract method is declared abstract and has no method body.

A class that contains an abstract method must be abstract.

Final classes and methods

A method marked final in a base class can't be overridden in any class that extends the base class. A data member declared final can't be modified once it has been initialized. A data member that is public, final, and static is treated the same as a constant in other languages:

class TV
{
 public final static int HISTORY_CHANNEL = 20;
 .
 .
 .
}


Arrays

Arrays of intrinsic types

The following code declares a reference to an array of integers:

int array[];


The brackets following array indicate that this is a reference to an array; however, no number within the brackets is required (or allowed), because the declaration itself doesn't allocate the space for the array. You can place the bracket before or after the reference name. Thus, the following code is also allowed (and is more common):

int[] array;


The memory for the array is allocated off of the heap:

int[] array = new int[5]; // allocate room for five integers


You can use an initialization list when declaring an array as follows:

int[]array = new int[]{0, 1, 2, 3, 4};


This statement allocates an array of five integers off of the heap, and assigns them the values 0 through 4.

Elements within an array are accessed using the brackets as well:

// initialize the array to zeros for (int i = 0; i < 5; i++)
{
 array[i] = 0;
}


Java checks the range of every subscript. Thus, if i were not in the range of 0 through 5, the statement array[i] would generate an ArrayIndexOutOfBoundsException error.

Arrays of objects

The declaration of an array creates room for the array, but it doesn't initialize the elements of the array. The following does NOT create an array of five TV objects:

TV [] tvArray = new TV [5];


Instead, this creates an array of five references to TV objects, all of which point to the null object. You can use a loop to allocate each of the TV objects individually, as follows:

TV[] tvArray = new TV[5];
for (int i = 0; i < 5; i++)
{
 tvArray[i] = new TV();
}


The objects in an array can also be initialized when you allocate them, as follows:

TV[] tvArray = new TV[] {new BWTV(),
 new ColorTV(128, 128, 128),
 new HDTV(),
 null, null};


The first three objects declared are different subtypes of TV. The final two entries refer to the null object, which is of all class types.

Array class

An array is an object of class Array. All arrays have the public data property length, which contains the number of elements defined in the array.

Inner Classes

Class definitions can be nested as shown in the following example:

class ColorTV extends TV
{
 class Tuner extends Receiver
 {
 float frequency;
 void tune(float frequency)
 {
 }
 }
}


The class Tuner is an inner class to the class ColorTV. The members of ColorTV (including this) are accessible to the members of Tuner. The reverse isn't true, however. Notice that inner classes can extend other classes.

Interfaces

A Java class can't extend more than one class. Java does offer a related concept called interfaces, which relieves much of the necessity for multiple inheritance.

Except for the appearance of the keyword interface instead of the keyword class, the declaration of an interface is similar to that of a class in which all of the methods are abstract. An interface allows you to describe a set of capabilities that a class must implement. For example, consider the following interface definition:

interface ITunable
{
 void tune(int);
 String receive();
}


This interface definition represents a promise to implement the method tune(). (Beginning the name of an interface with a capital 'I' is a coding convention.)

The ITunable interface could be used in a method as follows:

class ReceiveNews extends News
{
 void display(ITunable rcvr)
 {
 // first tune the receiver
 rcvr.tune(NEWS_CHANNEL);
 //receive the news currently available
 String s;
 while((s = rcvr.receive).length != 0)
 {
 .
 .
 .
 }
 }
}


Here, the class ReceiveNews is prepared to receive as an argument to its display() method any class that implements the tune() and receive() methods to receive and display the news. The class TV() could be used if it were prepared to implement those two methods:

class TV extends HouseHoldDevice implements ITunable
{
 void tune(int channel)
 {
 .
 .
 .
 }
 String receive()
 {
 .
 .
 .
 }
}
class NewsRoom
{
 ReceiveNews rcvr = new ReceiveNews();
 TV tv = new TV();
 void work()
 {
 // use the TV to receive the news
 rcvr.display(tv);
 }
}


Here, the class TV extends the class HouseHoldDevice in order to inherit the properties necessary to work within the house. At the same time, TV implements the ITunable interface by implementing the tune() and receive() methods.

The class NewsRoom contains a data member rcvr of class ReceiveNews, which it uses to display the news. The method NewsRoom.work() calls ReceiveNews.display(), passing it a TV object. This is allowed because ReceiveNews.display() knows that TV implements both the tune() and receive() methods, since TV implements the ITunable interface.

A class that implements an interface, but which doesn't override all of the methods of the interface, must be abstract. Comments