WebReference.com - Part 5 of chapter 5 from Beginning Java 2 SDK 1.4 Edition, Wrox Press Ltd (2/6)
[previous] [next] |
Beginning Java 2 SDK 1.4 Edition
Static Nested Classes
To make objects of a nested class type independent of objects of the enclosing class, you can
declare the nested class as static
. For example,
public class Outside {
public static class Skinside {
// Details of Skinside
}
// Nested class
public class Inside {
// Details of Inside class...
}
// More members of Outside class...
}
Now with Skinside
inside Outside
declared as static
, we can
declare objects of this nested class, independent from objects of Outside
, and regardless
of whether we have created any Outside
objects or not. For example:
Let's see how a nested class works in practice with a simple example. We will create a class
MagicHat
that will define an object containing a variable number of rabbits. We will put
the definition for the class Rabbit
inside the definition of the class MagicHat
.
The basic structure of MagicHat.java
will be:
public class MagicHat {
// Definition of the MagicHat class...
// Nested class to define a rabbit
static class Rabbit {
// Definition of the Rabbit class...
}
}
Here the nested class is defined as static
because we want to be able to have static
members of this class. We will see a little later how it might work with a non-static nested class.
Try It Out--Rabbits Out of Hats
Let's add the detail of the MagicHat
class definition:
import java.util.Random; // Import Random class
public class MagicHat {
static int maxRabbits = 5; // Maximum rabbits in a hat
static Random select = new Random(); // Random number generator
// Constructor for a hat
public MagicHat(String hatName) {
this.hatName = hatName; // Store the hat name
rabbits = new Rabbit[1+select.nextInt(maxRabbits)]; // Random rabbits
for(int i = 0; i < rabbits.length; i++)
rabbits[i] = new Rabbit(); // Create the rabbits
}
// String representation of a hat
public String toString() {
// Hat name first...
String hatString = "\n" + hatName + " contains:\n";
for(int i = 0; i < rabbits.length; i++)
hatString += "\t" + rabbits[i] + " "; // Add the rabbits strings
return hatString;
}
private String hatName; // Name of the hat
private Rabbit rabbits[]; // Rabbits in the hat
// Nested class to define a rabbit
static class Rabbit {
// Definition of the Rabbit class...
}
}
Instead of the old Math.random()
method that we have been using up to now to generate
pseudo-random values, we are using an object of the class Random
that is defined in the
package java.util
. An object of type Random
has a variety of methods to
generate pseudo-random values of different types, and with different ranges. The method nextInt()
that we are using here returns an integer that is zero or greater, but less than the integer value you
pass as an argument. Thus if you pass the length of an array to it, it will generate a random index
value that will always be legal for the array size.
We can now add the definition of the Rabbit
class. When we create a Rabbit
object, we want it to have a unique name so we can distinguish one Rabbit
from another.
We can generate unique names by selecting one from a limited set of fixed names, and then appending an
integer that is different each time the base name is used. Here's what we need to add for the
Rabbit
class definition:
public class MagicHat {
// Definition of the MagicHat class--as before...
// Nested class to define a rabbit
static class Rabbit {
// A name is a rabbit name from rabbitNames followed by an integer
static private String[] rabbitNames = {"Floppsy", "Moppsy",
"Gnasher", "Thumper"};
static private int[] rabbitNamesCount = new int[rabbitNames.length];
private String name; // Name of the rabbit
// Constructor for a rabbit
public Rabbit() {
int index = select.nextInt(rabbitNames.length); // Get random name index
name = rabbitNames[index] + (++rabbitNamesCount[index]);
}
// String representation of a rabbit
public String toString() {
return name;
}
}
}
Note that the constructor in the Rabbit
class can access the select
member
of the enclosing class MagicHat
, without qualification. This is only possible with static
members of the enclosing class--you can't refer to non-static members of the enclosing class here
because there is no object of type MagicHat
associated with it.
We can use the following application class to try out our nested class:
public class TryNestedClass {
static public void main(String[] args) {
// Create three magic hats and output them
System.out.println(new MagicHat("Gray Topper"));
System.out.println(new MagicHat("Black Topper"));
System.out.println(new MagicHat("Baseball Cap"));
}
}
When I ran the program, I got the output:
Gray Topper contains:
Moppsy1 Moppsy2 Floppsy1
Black Topper contains:
Thumper1 Moppsy3 Thumper2 Gnasher1
Baseball Cap contains:
Moppsy4 Moppsy5 Thumper3
You are likely to get something different.
How it Works
Each MagicHat
object will contain a random number of Rabbit
objects. The
constructor for a MagicHat
object stores the name of the hat in its private member
hatName
, and generates a Rabbit
array with at least one, and up to
maxRabbits
elements. This is done with the expression
1+select.nextInt(maxRabbits)
. Calling nextInt()
with the argument
maxRabbits
will return a value that is from 0
to maxRabbits-1
inclusive. Adding 1
to this will result in a value from 1
to
maxRabbits
inclusive. The array so created is then filled with Rabbit
objects.
The MagicHat
class also has a method toString()
method which returns a
String
object containing the name of the hat and the names of all the rabbits in the hat.
This assumes that the Rabbit
class also has a toString()
method defined. We
will be able to use the toString()
implicitly in an output statement when we come to
create and display MagicHat
class objects.
The base names that we use to generate rabbit names are defined in the static array
rabbitNames[]
in the Rabbit
class. The count for each base name, which we will
append to the base name to produce a unique name for a rabbit, is stored in the static array
rabbitNamesCount[]
. This has the same number of elements as the rabbitNames
array, and each element stores a value to be appended to the corresponding name in the
rabbitNames
array. The Rabbit
class has the data member, name
, to
store a name that is initialized in the constructor. A random base name is selected from the
rabbitNames[]
array using an index value from 0
up to one less than the length
of this array. We then append the current count for the name incremented by 1
, so successive
uses of any base name such as Gnasher
, for example, will produce names Gnasher1
,
Gnasher2
, and so on. The toString()
method for the class returns the name for
the Rabbit
object.
The method main()
in TryNestedClass
creates three MagicHat
objects and outputs the string representation of each of them. Putting the object as an argument to the
println()
method will call the toString()
method for the object automatically,
and the String
object that is returned will be output to the screen.
[previous] [next] |
Created: August 5, 2002
Revised: August 5, 2002
URL: https://webreference.com/programming/java/beginning/chap5/5/2.html