System, but they may not be reproduced for publication



Yüklə 83 Mb.
Pdf görüntüsü
səhifə57/82
tarix19.04.2023
ölçüsü83 Mb.
#106251
1   ...   53   54   55   56   57   58   59   60   ...   82
Java A Beginner’s Guide, Eighth Edition ( PDFDrive )

generic method.


Ask the Expert
Q
: I have heard that Java’s generics are similar to templates in C++. Is
this the case?
A
: Java generics are similar to templates in C++. What Java calls a parameterized
type, C++ calls a template. However, Java generics and C++ templates are not the
same, and there are some fundamental differences between the two approaches to
generic types. For the most part, Java’s approach is simpler to use.
A word of warning: If you have a background in C++, it is important not to jump to
conclusions about how generics work in Java. The two approaches to generic code
differ in subtle but fundamental ways.
A principal advantage of generic code is that it will automatically work with the type of
data passed to its type parameter. Many algorithms are logically the same no matter
what type of data they are being applied to. For example, a Quicksort is the same
whether it is sorting items of type Integer, String, Object, or Thread. With generics,
you can define an algorithm once, independently of any specific type of data, and then
apply that algorithm to a wide variety of data types without any additional effort.
It is important to understand that Java has always given you the ability to create
generalized classes, interfaces, and methods by operating through references of type
Object. Because Object is the superclass of all other classes, an Object reference can
refer to any type of object. Thus, in pre­generics code, generalized classes, interfaces,
and methods used Object references to operate on various types of data. The problem
was that they could not do so with type safety because casts were needed to explicitly
convert from Object to the actual type of data being operated upon. Thus, it was
possible to accidentally create type mismatches. Generics add the type safety that was
lacking because they make these casts automatic and implicit. In short, generics expand
your ability to reuse code and let you do so safely and reliably.
A SIMPLE GENERICS EXAMPLE
Before discussing any more theory, it’s best to look at a simple generics example. The
following program defines two classes. The first is the generic class Gen, and the
second is GenDemo, which uses Gen.



The output produced by the program is shown here:
Let’s examine this program carefully. First, notice how Gen is declared by the following
line:
Here, T is the name of a type parameter. This name is used as a placeholder for the
actual type that will be passed to Gen when an object is created. Thus, T is used within
Gen whenever the type parameter is needed. Notice that T is contained within < >.
This syntax can be generalized. Whenever a type parameter is being declared, it is
specified within angle brackets. Because Gen uses a type parameter, Gen is a generic
class.
In the declaration of Gen, there is no special significance to the name T. Any valid
identifier could have been used, but T is traditional. Furthermore, it is recommended
that type parameter names be single­character, capital letters. Other commonly used
type parameter names are V and E. One other point about type parameter names:
Beginning with JDK 10, you cannot use var as the name of a type parameter.
Next, T is used to declare an object called ob, as shown here:
As explained, T is a placeholder for the actual type that will be specified when a Gen
object is created. Thus, ob will be an object of the type passed to T. For example, if type
String is passed to T, then in that instance, ob will be of type String.
Now consider Gen’s constructor:
Notice that its parameter, o, is of type T. This means that the actual type of o is
determined by the type passed to T when a Gen object is created. Also, because both
the parameter o and the member variable ob are of type T, they will both be of the


same actual type when a Gen object is created.
The type parameter T can also be used to specify the return type of a method, as is the
case with the getob( ) method, shown here:
Because ob is also of type T, its type is compatible with the return type specified by
getob( ).
The showType( ) method displays the type of T. It does this by calling getName( )
on the Class object returned by the call to getClass( ) on ob. We haven’t used this
feature before, so let’s examine it closely. As you should recall from 
Chapter 7
, the
Object class defines the method getClass( ). Thus, getClass( ) is a member of all
class types. It returns a Class object that corresponds to the class type of the object on
which it is called. Class is a class defined within java.lang that encapsulates
information about a class. Class defines several methods that can be used to obtain
information about a class at run time. Among these is the getName( ) method, which
returns a string representation of the class name.
The GenDemo class demonstrates the generic Gen class. It first creates a version of
Gen for integers, as shown here:
Look carefully at this declaration. First, notice that the type Integer is specified within
the angle brackets after Gen. In this case, Integer is a type argument that is passed to
Gen’s type parameter, T. This effectively creates a version of Gen in which all
references to T are translated into references to Integer. Thus, for this declaration, ob
is of type Integer, and the return type of getob( ) is of type Integer.
Before moving on, it’s necessary to state that the Java compiler does not actually create
different versions of Gen, or of any other generic class. Although it’s helpful to think in
these terms, it is not what actually happens. Instead, the compiler removes all generic
type information, substituting the necessary casts, to make your code behave as if a
specific version of Gen was created. Thus, there is really only one version of Gen that
actually exists in your program. The process of removing generic type information is
called erasure, which is discussed later in this chapter.


The next line assigns to iOb a reference to an instance of an Integer version of the
Gen class.
Notice that when the Gen constructor is called, the type argument Integer is also
specified. This is because the type of the object (in this case iOb) to which the reference
is being assigned is of type Gen. Thus, the reference returned by new must
also be of type Gen. If it isn’t, a compile­time error will result. For example,
the following assignment will cause a compile­time error:
Because iOb is of type Gen, it can’t be used to refer to an object of
Gen. This type of checking is one of the main benefits of generics because it
ensures type safety.
As the comments in the program state, the assignment
makes use of autoboxing to encapsulate the value 88, which is an int, into an Integer.
This works because Gen creates a constructor that takes an Integer
argument. Because an Integer is expected, Java will automatically box 88 inside one.
Of course, the assignment could also have been written explicitly, like this:
However, there would be no benefit to using this version.
The program then displays the type of ob within iOb, which is Integer. Next, the
program obtains the value of ob by use of the following line:
Because the return type of getob( ) is T, which was replaced by Integer when iOb was
declared, the return type of getob( ) is also Integer, which auto­unboxes into int
when assigned to v (which is an int). Thus, there is no need to cast the return type of
getob( ) to Integer.
Next, GenDemo declares an object of type Gen:


Because the type argument is String, String is substituted for T inside Gen. This
creates (conceptually) a String version of Gen, as the remaining lines in the program
demonstrate.
Generics Work Only with Reference Types
When declaring an instance of a generic type, the type argument passed to the type
parameter must be a reference type. You cannot use a primitive type, such as int or
char. For example, with Gen, it is possible to pass any class type to T, but you cannot
pass a primitive type to T. Therefore, the following declaration is illegal:
Of course, not being able to specify a primitive type is not a serious restriction because
you can use the type wrappers (as the preceding example did) to encapsulate a
primitive type. Further, Java’s autoboxing and auto­unboxing mechanism makes the
use of the type wrapper transparent.
Generic Types Differ Based on Their Type Arguments
A key point to understand about generic types is that a reference of one specific version
of a generic type is not type­compatible with another version of the same generic type.
For example, assuming the program just shown, the following line of code is in error
and will not compile:
Even though both iOb and strOb are of type Gen, they are references to different
types because their type arguments differ. This is part of the way that generics add type
safety and prevent errors.
A Generic Class with Two Type Parameters
You can declare more than one type parameter in a generic type. To specify two or more
type parameters, simply use a comma­separated list. For example, the following
TwoGen class is a variation of the Gen class that has two type parameters:


The output from this program is shown here:


Notice how TwoGen is declared:
It specifies two type parameters, T and V, separated by a comma. Because it has two
type parameters, two type arguments must be passed to TwoGen when an object is
created, as shown next:
In this case, Integer is substituted for T, and String is substituted for V. Although the
two type arguments differ in this example, it is possible for both types to be the same.
For example, the following line of code is valid:
In this case, both T and V would be of type String. Of course, if the type arguments
were always the same, then two type parameters would be unnecessary.
The General Form of a Generic Class
The generics syntax shown in the preceding examples can be generalized. Here is the
syntax for declaring a generic class:

Yüklə 83 Mb.

Dostları ilə paylaş:
1   ...   53   54   55   56   57   58   59   60   ...   82




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə