Java Reference
In-Depth Information
printArray generic method with the additional parameters lowSubscript and highSub-
script to specify the portion of the array to output (see Exercise 20.5).
A generic method can also be overloaded by nongeneric methods. When the compiler
encounters a method call, it searches for the method declaration that best matches the
method name and the argument types specified in the call—an error occurs if two or more
overloaded methods both could be considered best matches. For example, generic method
printArray of Fig. 20.3 could be overloaded with a version that's specific to String s,
which outputs the String s in neat, tabular format (see Exercise 20.6).
20.6 Generic Classes
The concept of a data structure, such as a stack, can be understood independently of the el-
ement type it manipulates. Generic classes provide a means for describing the concept of a
stack (or any other class) in a type-independent manner. We can then instantiate type-specific
objects of the generic class. Generics provide a nice opportunity for software reusability.
Once you have a generic class, you can use a simple, concise notation to indicate the
type(s) that should be used in place of the class's type parameter(s). At compilation time,
the compiler ensures the type safety of your code and uses the erasure techniques described
in Sections 20.3-20.4 to enable your client code to interact with the generic class.
One generic Stack class, for example, could be the basis for creating many logical
Stack classes (e.g., “ Stack of Double ,” “ Stack of Integer ,” “ Stack of Character ,” “ Stack
of Employee ”). These classes are known as parameterized classes or parameterized types
because they accept one or more type parameters. Recall that type parameters represent
only reference types , which means the Stack generic class cannot be instantiated with prim-
itive types. However, we can instantiate a Stack that stores objects of Java's type-wrapper
classes and allow Java to use autoboxing to convert the primitive values into objects. Recall
that autoboxing occurs when a value of a primitive type (e.g., int ) is pushed onto a Stack
that contains wrapper-class objects (e.g., Integer ). Auto-unboxing occurs when an object
of the wrapper class is popped off the Stack and assigned to a primitive-type variable.
Implementing a Generic Stack Class
Figure 20.7 declares a generic Stack class for demonstration purposes—the java.util
package already contains a generic Stack class. A generic class declaration looks like a non-
generic one, but the class name is followed by a type-parameter section (line 5). In this case,
type parameter T represents the element type the Stack will manipulate. As with generic
methods, the type-parameter section of a generic class can have one or more type param-
eters separated by commas. (You'll create a generic class with two type parameters in
Exercise 20.8.) Type parameter T is used throughout the Stack class declaration to repre-
sent the element type. This example implements a Stack as an ArrayList .
Class Stack declares variable elements as an ArrayList<T> (line 7). This ArrayList
will store the Stack 's elements. As you know, an ArrayList can grow dynamically, so
objects of our Stack class can also grow dynamically. The Stack class's no-argument con-
structor (lines 10-13) invokes the one-argument constructor (lines 16-20) to create a
Stack in which the underlying ArrayList has a capacity of 10 elements. The one-argu-
ment constructor can also be called directly to create a Stack with a specified initial
capacity. Line 18 validates the constructor's argument. Line 19 creates the ArrayList of
the specified capacity (or 10 if the capacity was invalid).
 
 
Search WWH ::




Custom Search