0% found this document useful (0 votes)
18 views28 pages

Chapter 14 Generics

Uploaded by

Al Shahrear Emon
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views28 pages

Chapter 14 Generics

Uploaded by

Al Shahrear Emon
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 28

Chapter 14: Generics

Dr. Mohammad Rashedur Rahman


Introduction
• Since the original 1.0 release in 1995, many new features have been added to
Java. One that has had a profound impact is generics.
• Introduced by JDK 5, generics changed Java in two important ways. First, it
added a new syntactical element to the language. Second, it caused changes to
many of the classes and methods in the core API.
• Through the use of generics, it is possible to create classes, interfaces, and
methods that will work in a type-safe manner with various kinds of data.
• For example, the mechanism that supports a stack is the same whether that
stack is storing 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.
What are the generics?
• At its core, the term generics means parameterized types.
• Parameterized types are important because they enable you to create
classes, interfaces, and methods in which the type of data upon which
they operate is specified as a parameter.
• Using generics, it is possible to create a single class, for example, that
automatically works with different types of data.
• A class, interface, or method that operates on a parameterized type is
called generic, as in generic class or generic method.
Details of Generic
Declaration
• First, notice how Gen is declared.
• 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, which is also called a
parameterized type.
Details of Declaration (cont..)
• 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:
Details of Declaration (cont..)
• 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
by calling getName( ) on the Class object
returned by the call to getClass( ) on ob.
• The getClass( ) method is defined by Object
and is thus a member of all class types. It
returns a Class object that corresponds to the
type of the class of the object on which it is
called.
• Class defines the getName( ) method, which
returns a string representation of the class
name.
Details of Implementation
(cont..)
• The GenDemo class demonstrates the generic
Gen class. It first creates a version of Gen for
integers, as shown here:
• Gen<Integer> iOb;
• 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
Reference type should be used with
Generics
• 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 a type parameter. Therefore, the following
declaration is illegal:
Gen<int> intOb = new Gen<int>(53); // Error, can't use primitive type
• 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.
What Compiler does with generics?
• 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 were 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
Non Generic
Version
How Generics Improve Type
Safety?
• Given that the same functionality found in the generic Gen class can be
achieved without generics, by simply specifying Object as the data type and
employing the proper casts, what is the benefit of making Gen generic?
• Benefits:
• First, explicit casts must be employed to retrieve the stored data if you do not use
generic concept.
• Notice this line
int v = (Integer) iOb.getob();
• Because the return type of getob( ) is Object, the cast to Integer is necessary to enable
that value to be auto-unboxed and stored in v.
• If you remove the cast, the program will not compile.
• With the generic version, this cast was implicit. In the non-generic version, the cast must
be explicit. This is not only an inconvenience, but also a potential source of error.
How Generics Improve Type
Safety? (cont..)
• Second, many kinds of type mismatch errors cannot be found until run time if
you do not use generics.
• Consider the following sequence from near the end of the program:
// This compiles, but is conceptually wrong!
iOb = strOb;
v = (Integer) iOb.getob(); // run-time error!
• Here, strOb is assigned to iOb. However, strOb refers to an object that contains a string,
not an integer.
• This assignment is syntactically valid because all NonGen references are the same, and
any NonGen reference can refer to any other NonGen object.
• However, the statement is semantically wrong, as the next line shows. Here, the return
type of getob( ) is cast to Integer, and then an attempt is made to assign this value to v.
• The trouble is that iOb now refers to an object that stores a String, not an Integer.
Bounded Types and use extends in
generic class
• In the preceding examples, the type parameters
could be replaced by any class type.
• This is fine for many purposes, but sometimes it is
useful to limit the types that can be passed to a
type parameter.
• For example, assume that you want to create a
generic class that contains a method that returns
the average of an array of numbers.
• Furthermore, you want to use the class to obtain
the average of an array of any type of number,
including integers, floats, and doubles.
• The trouble is that the compiler has no way to
know that you are intending to create Stats objects
using only numeric types.
• Thus, when you try to compile Stats, an error is
reported that indicates that the doubleValue( )
method is unknown
Bounded Types and use extends in generic
class (Cont..)
• To handle such situations, Java provides
bounded types.
• When specifying a type parameter, you can
create an upper bound that declares the
superclass from which all type arguments must
be derived.
• This is accomplished through the use of an
extends clause when specifying the type
parameter
Necessity of Generic Method
1 // Fig. 18.1: OverloadedMethods.java
2 // Using overloaded methods to print array of different types.
3
4 public class OverloadedMethods
5 {
6 // method printArray to print Integer array
7 public static void printArray( Integer[] inputArray )
8 { Method printArray accepts
9 // display array elements an array of Integer objects
10 for ( Integer element : inputArray )
11 System.out.printf( "%s ", element );
12
13 System.out.println();
14 } // end method printArray
15
16 // method printArray to print Double array
17 public static void printArray( Double[] inputArray )
18 { Method printArray accepts
19 // display array elements an array of Double objects
20 for ( Double element : inputArray )
21 System.out.printf( "%s ", element );
22
23 System.out.println();
24 } // end method printArray
25

15
16

Necessity of Generic Method (cont..)


26 // method printArray to print Character array
27 public static void printArray( Character[] inputArray )
28 {
Method printArray accepts
an array of Character objects
29 // display array elements
30 for ( Character element : inputArray )
31 System.out.printf( "%s ", element );
32
33 System.out.println();
34 } // end method printArray
35
36 public static void main( String args[] )
37 {
38 // create arrays of Integer, Double and Character
39 Integer[] integerArray = { 1, 2, 3, 4, 5, 6 };
40 Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 };
41 Character[] characterArray = { 'H', 'E', 'L', 'L', 'O' };
42
Auto-boxing happens here…
Necessity of Generic Method
43 System.out.println( "Array integerArray contains:" );
44 printArray( integerArray ); // pass an Integer array
45 System.out.println( "\nArray doubleArray contains:" );
46 printArray( doubleArray ); // pass a Double array
47 System.out.println( "\nArray characterArray contains:" );
48 At compile
printArray( characterArray ); // pass a Character time, compiler determines argument
array
49 } // end main integerArray’s type (i.e., Integer[]), attempts
50 } // end class OverloadedMethods to locate a method named printArray that
specifies a single Integer[] parameter (lines 7-14)
Array integerArray contains:
1 2 3 4 5 6

Array doubleArray contains:


1.1 2.2 3.3 4.4 5.5 6.6 7.7

Array characterArray contains:


H E L L O
Motivation for Generic Methods (Cont.)

• The three printArray methods


• Array element type appears in two location
• Method header
• for statement header
• Combine three printArray methods into one
• Replace element types with a generic name E
• Declare one printArray method
• Display string representation of the elements of any
array
Towards generic method
1 public static void printArray( E[] inputArray )
2 {
Replace the element type with
3 // display array elements a single generic type E
4 for ( E element : inputArray )
5 System.out.printf( "%s ", element );
6
7 System.out.println();
8 } // end method printArray

Actual syntax:
public static < E > void printArrays( E[] array)
Type parameter section, also called formal
type parameters
 Delimited by angle brackets ( < and > )
 Precede the method’s return type
 Contain one or more type parameters
19
Generic Methods: type parameter

• Type parameter, also known as type variable


• An identifier that specifies a generic type name
• Act as placeholders for the types of the argument passed to
the generic method, i.e., actual type arguments
• Usually use a capital letter
• Convention: use E (element) for a type parameter that represents
the type of an element in an array (or other collection)
• Can be used in return type, parameter types and local
variable types
• Can be declared only once but can appear more than once:
public static < E > void printTwoArrays(
E[] array1, E[] array2 )

20
1 // Fig. 18.3: GenericMethodTest.java
2 // Using generic methods to print array of different types.
Use the type parameter to declare
3
method printArray’s parameter type
4 public class GenericMethodTest
5 {
6 // generic method printArray
7 public static < E > void printArray( E[] inputArray )
8 {
9 // display array elements Type parameter section delimited
10 for ( E element : inputArray )
by angle brackets (< and > )
11 System.out.printf( "%s ", element );
12
Use the type parameter to declare method
13 System.out.println();
printArray’s local variable type
14 } // end method printArray
15
16 public static void main( String args[] )
17 {
18 // create arrays of Integer, Double and Character
19 Integer[] intArray = { 1, 2, 3, 4, 5 };
20 Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 };
21 Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
22

21
23 System.out.println( "Array integerArray contains:" );
24 printArray( integerArray ); // pass an Integer array
Invoke generic method printArray
25 System.out.println( "\nArray doubleArray contains:" );
with an Integer array
26 printArray( doubleArray ); // pass a Double array
27 System.out.println( "\nArray characterArray contains:" );
28 printArray( characterArray ); // pass a Character array
29 } // end main
30 } // end class GenericMethodTest

Array integerArray contains:


1 2 3 4 5 6 Invoke generic method printArray
with a Character array
Array doubleArray contains:
1.1 2.2 3.3 4.4 5.5 6.6 7.7

Array characterArray contains:


H E L L O

22
Generic Interface:
Comparable
public interface Comparable<T>
{
int compareTo(T other);
}
• compareTo(): Compare two objects (this and other) of type T
• Return 0 if two objects are equal
• Return -1 if this is less than other
• Return 1 if this is greater than other
• Comparable is an interface declared in java.lang.
• A class that implements Comparable defines objects that can be ordered

23
Upper bound of type parameter

• Next example, generic method maximum (x,y,z)


• Call compareTo method to compare two objects
• Actual type must implement Comparable interface

24
1 // Fig. 18.5: MaximumTest.java
2 // Generic method maximum returns the largest of three objects.
3
4 public class MaximumTest Type parameter is used in the
5 { return type of method maximum
6 // determines the largest of three Comparable objects
7 public static < T extends Comparable< T > > T maximum( T x, T y, T z )
8 {
9 T max = x; // assume x is initially the largest
only object of classes that implement
10 interface Comparable can be used
11 if ( y.compareTo( max ) > 0 )
12 max = y; // y is the largest so far
13
14 if ( z.compareTo( max ) > 0 )
15 max = z; // z is the largest
16 Invokes method compareTo method
17 Comparable to compare z and max
return max; // returns the largest object
18 } // end method maximum
19

Generic interface: with a single interface declaration, a set of related types


E.g., Comparable< T >, all types that implement interface Comparable

25
20 public static void main( String args[] )
21 {
22 System.out.printf( "Maximum of %d, %d and %d is %d\n\n", 3, 4, 5,
23 maximum( 3, 4, 5 ) );
24 System.out.printf( "Maximum of %.1f, %.1f and %.1f is %.1f\n\n",
25 6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );
26 System.out.printf( "Maximum of %s, %s and %s is %s\n", "pear",
27 "apple", "orange", maximum( "pear", "apple", "orange" ) );
28 } // end main Invoke generic method
29 } // end class MaximumTest maximum with three strings

Maximum of 3, 4 and 5 is 5

Maximum of 6.6, 8.8 and 7.7 is 8.8

Maximum of pear, apple and orange is pear

26
Compile-Time Translation

• Upper bound of type parameter: constraints on actual type


• Default is Object
• use keyword extends to specify
• E.g., T extends Comparable< T >
• When compiler translates generic method to Java bytecode
• Replaces type parameter with its upper bound
• Insert explicit cast operation
e.g., line 23 of Fig. 18.5 I preceded by an Integer cast
(Integer) maximum( 3, 4, 5 )
Generic Constructor
• It is possible for constructors to
be generic, even if their class is
not.
• Because GenCons( ) specifies a
parameter of a generic type,
which must be a subclassof
Number, GenCons( ) can be
called with any numeric type,
including Integer, Float, or
Double.
• Therefore, even though
GenCons is not a generic class,
its constructor is generic

You might also like