Wildcards in Methods That Accept Type Parameters

In this section, we introduce a powerful generics concept known as wildcards. For this purpose, we will also introduce a new data structure from package java.util. Chapter 19, Collections, discusses the Java Collections Framework, which provides many generic data structures and algorithms that manipulate the elements of those data structures. Perhaps the simplest of these data structures is class ArrayLista dynamically resizable, array-like data structure. As part of this discussion, you will learn how to create an ArrayList, add elements to it and traverse those elements using an enhanced for statement.

Before we introduce wildcards, let's consider an example that helps us motivate their use. Suppose that you would like to implement a generic method sum that totals the numbers in a collection, such as an ArrayList. You would begin by inserting the numbers in the collection. As you know, generic classes can be used only with class or interface types. So the numbers would be autoboxed as objects of the type-wrapper classes. For example, any int value would be autoboxed as an Integer object, and any double value would be autoboxed as a Double object. We'd like to be able to total all the numbers in the ArrayList regardless of their type. For this reason, we'll declare the ArrayList with the type argument Number, which is the superclass of both Integer and Double. In addition, method sum will receive a parameter of type ArrayList< Number > and total its elements. Figure 18.14 demonstrates totaling the elements of an ArrayList of Numbers.

Figure 18.14. Totaling the numbers in an ArrayList< Number >.

(This item is displayed on page 895 in the print version)

 1 // Fig. 18.14: TotalNumbers.java
 2 // Summing the elements of an ArrayList.
 3 import java.util.ArrayList;
 4
 5 public class TotalNumbers
 6 {
 7 public static void main( String args[] )
 8 {
 9 // create, initialize and output ArrayList of Numbers containing
10 // both Integers and Doubles, then display total of the elements
11 Number[] numbers = { 1, 2.4, 3, 4.1 }; // Integers and Doubles
12 ArrayList< Number > numberList = new ArrayList< Number >(); 
13
14 for ( Number element : numbers )
15 numberList.add( element ); // place each number in numberList
16
17 System.out.printf( "numberList contains: %s
", numberList );
18 System.out.printf( "Total of the elements in numberList: %.1f
",
19 sum( numberList ) );
20 } // end main
21
22 // calculate total of ArrayList elements
23 public static double sum( ArrayList< Number > list )
24 {
25 double total = 0; // initialize total
26
27 // calculate sum
28 for ( Number element : list ) 
29  total += element.doubleValue();
30
31 return total;
32 } // end method sum
33 } // end class TotalNumbers
 
numberList contains: [1, 2.4, 3, 4.1]
Total of the elements in numberList: 10.5
 

Line 11 declares and initializes an array of Numbers. Because the initializers are primitive values, Java autoboxes each primitive value as an object of its corresponding wrapper type. The int values 1 and 3 are autoboxed as Integer objects, and the double values 2.4 and 4.1 are autoboxed as Double objects. Line 12 declares and creates an ArrayList object that stores Numbers and assigns it to variable numberList. Note that we do not have to specify the size of the ArrayList because it will grow automatically as we insert objects.

Lines 1415 traverse array numbers and place each element in numberList. Method add of class ArrayList appends an element to the end of the collection. Line 17 outputs the contents of the ArrayList as a String. This statement implicitly invokes the ArrayList's toString method, which returns a string of the form "[ elements ]" in which elements is a comma-separated list of the elements' string representations. Lines 1819 display the sum of the elements that is returned by the call to method sum at line 19.

Method sum (lines 2332) receives an ArrayList of Numbers and calculates the total of the Numbers in the collection. The method uses double values to perform the calculations and returns the result as a double. Line 25 declares local variable total and initializes it to 0. Lines 2829 use the enhanced for statement, which is designed to work with both arrays and the collections of the Collections Framework, to total the elements of the ArrayList. The for statement assigns each Number in the ArrayList to variable element, then uses method doubleValue of class Number to obtain the Number's underlying primitive value as a double value. The result is added to total. When the loop terminates, the method returns the total.

Implementing Method sum With a Wildcard Type Argument in Its Parameter

Recall that the purpose of method sum in Fig. 18.14 was to total any type of Numbers stored in an ArrayList. We created an ArrayList of Numbers that contained both Integer and Double objects. The output of Fig. 18.14 demonstrates that method sum worked properly. Given that method sum can total the elements of an ArrayList of Numbers, you might expect that the method would also work for ArrayLists that contain elements of only one numeric type, such as ArrayList< Integer >. So we modified class TotalNumbers to create an ArrayList of Integers and pass it to method sum. When we compile the program, the compiler issues the following error message:

 sum(java.util.ArrayList) in TotalNumbersErrors
 cannot be applied to (java.util.ArrayList)

Although Number is the superclass of Integer, the compiler does not consider the parameterized type ArrayList< Number > to be a supertype of ArrayList< Integer >. If it were, then every operation we could perform on ArrayList< Number > would also work on an ArrayList< Integer >. Consider the fact that you can add a Double object to an ArrayList< Number > because a Double is a Number, but you cannot add a Double object to an ArrayList< Integer > because a Double is not an Integer. Thus, the subtype relationship does not hold.

How do we create a more flexible version of method sum that can total the elements of any ArrayList that contains elements of any subclass of Number? This is where wildcard type arguments are important. Wildcards enable you to specify method parameters, return values, variables or fields, etc. that act as supertypes of parameterized types. In Fig. 18.15, method sum's parameter is declared in line 50 with the type:

 ArrayList< ? extends Number >

 

Figure 18.15. Wildcard test program.

(This item is displayed on pages 896 - 897 in the print version)

 1 // Fig. 18.15: WildcardTest.java
 2 // Wildcard test program.
 3 import java.util.ArrayList;
 4
 5 public class WildcardTest
 6 {
 7 public static void main( String args[] )
 8 {
 9 // create, initialize and output ArrayList of Integers, then
10 // display total of the elements
11 Integer[] integers = { 1, 2, 3, 4, 5 };
12 ArrayList< Integer > integerList = new ArrayList< Integer >();
13
14 // insert elements in integerList
15 for ( Integer element : integers )
16 integerList.add( element );
17
18 System.out.printf( "integerList contains: %s
", integerList );
19 System.out.printf( "Total of the elements in integerList: %.0f

",
20 sum( integerList ) );
21
22 // create, initialize and output ArrayList of Doubles, then
23 // display total of the elements
24 Double[] doubles = { 1.1, 3.3, 5.5 };
25 ArrayList< Double > doubleList = new ArrayList< Double >();
26
27 // insert elements in doubleList
28 for ( Double element : doubles )
29 doubleList.add( element );
30
31 System.out.printf( "doubleList contains: %s
", doubleList );
32 System.out.printf( "Total of the elements in doubleList: %.1f

",
33 sum( doubleList ) );
34
35 // create, initialize and output ArrayList of Numbers containing
36 // both Integers and Doubles, then display total of the elements
37 Number[] numbers = { 1, 2.4, 3, 4.1 }; // Integers and Doubles
38 ArrayList< Number > numberList = new ArrayList< Number >();
39
40 // insert elements in numberList
41 for ( Number element : numbers )
42 numberList.add( element );
43
44 System.out.printf( "numberList contains: %s
", numberList );
45 System.out.printf( "Total of the elements in numberList: %.1f
",
46 sum( numberList ) );
47 } // end main
48
49 // calculate total of stack elements
50 public static double sum( ArrayList< ? extends Number > list )
51 {
52 double total = 0; // initialize total
53
54 // calculate sum
55 for ( Number element : list )
56 total += element.doubleValue();
57
58 return total;
59 } // end method sum
60 } // end class WildcardTest
 
integerList contains: [1, 2, 3, 4, 5]
Total of the elements in integerList: 15

doubleList contains: [1.1, 3.3, 5.5]
Total of the elements in doubleList: 9.9

numberList contains: [1, 2.4, 3, 4.1]
Total of the elements in numberList: 10.5
 

A wildcard type argument is denoted by a question mark ( ? ). A question mark by itself represents an "unknown type." In this case, the wildcard extends class Number, which means that the wildcard has an upper bound of Number. Thus, the unknown type argument must be either Number or a subclass of Number. With the parameter type shown here, method sum can receive an ArrayList argument that contains any type of Number, such as ArrayList< Integer > (line 20), ArrayList< Double > (line 33) or ArrayList< Number > (line 46).

Lines 1120 create and initialize an ArrayList< Integer > called integerList, output its elements and total its elements by calling method sum (line 20). Lines 2433 perform the same operations for an ArrayList< Double > called doubleList. Lines 3746 perform the same operations for an ArrayList< Number > called numberList that contains both Integers and Doubles.

In method sum (lines 5059), although the ArrayList argument's element types are not directly known by the method, they are known to be at least of type Number because the wildcard was specified with the upper bound Number. For this reason, line 56 is allowed because all Number objects have a doubleValue method.

Although wildcards provide flexibility when passing parameterized types to a method, they also have some disadvantages. Because the wildcard (?) in the method's header (line 50) does not specify a type parameter name, you cannot use it as a type name throughout the method's body (i.e., you cannot replace Number with ? in line 55). If the wildcard is specified without an upper bound, then only the methods of type Object can be invoked on values of the wildcard type. Also, methods that use wildcards in their parameter's type arguments cannot be used to add elements to a collection referenced by the parameter.

Common Programming Error 18.4

Using a wildcard in a method's type parameter section or using a wildcard as an explicit type of a variable in the method body is a syntax error.


Introduction to Computers, the Internet and the World Wide Web

Introduction to Java Applications

Introduction to Classes and Objects

Control Statements: Part I

Control Statements: Part 2

Methods: A Deeper Look

Arrays

Classes and Objects: A Deeper Look

Object-Oriented Programming: Inheritance

Object-Oriented Programming: Polymorphism

GUI Components: Part 1

Graphics and Java 2D™

Exception Handling

Files and Streams

Recursion

Searching and Sorting

Data Structures

Generics

Collections

Introduction to Java Applets

Multimedia: Applets and Applications

GUI Components: Part 2

Multithreading

Networking

Accessing Databases with JDBC

Servlets

JavaServer Pages (JSP)

Formatted Output

Strings, Characters and Regular Expressions

Appendix A. Operator Precedence Chart

Appendix B. ASCII Character Set

Appendix C. Keywords and Reserved Words

Appendix D. Primitive Types

Appendix E. (On CD) Number Systems

Appendix F. (On CD) Unicode®

Appendix G. Using the Java API Documentation

Appendix H. (On CD) Creating Documentation with javadoc

Appendix I. (On CD) Bit Manipulation

Appendix J. (On CD) ATM Case Study Code

Appendix K. (On CD) Labeled break and continue Statements

Appendix L. (On CD) UML 2: Additional Diagram Types

Appendix M. (On CD) Design Patterns

Appendix N. Using the Debugger

Inside Back Cover



Java(c) How to Program
Java How to Program (6th Edition) (How to Program (Deitel))
ISBN: 0131483986
EAN: 2147483647
Year: 2003
Pages: 615

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net