23.8. Key Terms

 
[Page 701]

21.6. Wildcards

What are wildcards? Listing 21.6 gives an example to demonstrate the needs they address. The example declares a generic max method for finding the maximum in a stack of numbers (lines 12 “22). The main method creates a stack of integer objects, adds three integers to the stack, and invokes the max method to find the maximum number in the stack.

Listing 21.6. WildCardDemo1.java
 1   public class   WildCardDemo1 {  2   public static void   main(String[] args) {  3  GenericStack<Integer>  intStack =   new   GenericStack<Integer>();  4     intStack.push(   1   );  // 1 is autoboxed into new Integer(1)  5     intStack.push(   2   );  6     intStack.push(   -     2   );  7  8     System.out.print(   "The max number is "   + max(intStack));  9   } 10 11  // Find the maximum in a stack of numbers  12   public static double   max(  GenericStack<Number>  stack) { 13   double   max = stack.pop().doubleValue();  // initialize max  14 15   while   (!stack.isEmpty()) { 16   double   value = stack.pop().doubleValue(); 17   if   (value > max) 18         max = value; 19     } 20 21   return   max; 22   } 23 } 

The program in Listing 21.6 has a compilation error in line 8 because intStack is not an instance of GenericStack<Number> . So you cannot invoke max(intStack) .

The fact is that Integer is a subtype of Number , but GenericStack<Integer> is not a subtype of GenericStack<Number> . To circumvent this problem, JDK 1.5 introduces wildcards. A wildcard represents a type in the form of ? , ? extends T , or ? super T , where T is a type.

The first form, ? , called an unbounded wildcard , is the same as ? extends Object . The second form, ? extends T , called a bounded wildcard , represents T or an unknown subtype of T . The third form, ? super T , called a lower bound wildcard , denotes T or an unknown supertype of T .

You can fix the error by replacing line 11 in Listing 21.6 as follows :

   public static double   max(  GenericStack<?   extends   Number>  stack) { 

<? extends Number> is a wildcard type that represents Number or a subtype of Number . So it is legal to invoke max(new GenericStack<Integer>()) or max(new GenericStack<Double>()) .

Listing 21.7 shows an example of using the ? wildcard in the print method that prints objects in a stack and empties the stack. <?> is a wildcard that represents any object type. It is equivalent to <? Extends Object> . What happens if you replace GenericStack<?> by GenericStack<Object> ? It would be wrong to invoke print(intStack) , because instack is not an instance of GenericStack<Object> . Please note that GenericStack<Integer> is not a subtype of GenericStack<Object> , although Integer is a subtype of Object .


[Page 702]
Listing 21.7. WildCardDemo2.java
 1   public class   WildCardDemo2 {  2   public static void   main(String[] args) {  3  GenericStack<Integer>  intStack =   new   GenericStack<Integer>();  4     intStack.push(   1   );  // 1 is autoboxed into new Integer(1)  5     intStack.push(   2   );  6     intStack.push(   -2   );  7  8     print(intStack);  9   } 10 11  /** Print objects and empties the stack */  12   public static void   print(  GenericStack<?>  stack) { 13   while   (!stack.isEmpty()) { 14       System.out.print(stack.pop() +   " "   ); 15     } 16   } 17 } 

When is the wildcard <? super T> needed? Consider the example in Listing 21.8. The example creates a stack of strings in stack1 (line 3) and a stack of objects in stack2 (line 4) and invokes add(stack1, stack2) (line 9) to add the strings in stack1 into stack2 . GenericStack<? super T> is used to declare stack2 in line 12. If <? super T> is replaced by <T> , a compilation error would occur on add(stack1, stack2) in line 9, because stack1 's type is GenericStack<String> and stack2 's type is GenericStack<Object> . <? super T> represents type T or a supertype of T . GenericStack<Object> is a subtype of GenericStack<? super String> .

Listing 21.8. WildCardDemo3.java
 1   public class   WildCardDemo3 {  2   public static void   main(String[] args) {  3  GenericStack<String>  stack1 =   new   GenericStack<String>();  4  GenericStack<Object>  stack2 =   new   GenericStack<Object>();  5     stack2.push(   "Java"   );  6     stack2.push(   2   );  7     stack1.push(   "Sun"   );  8  add(stack1, stack2);  9     WildCardDemo2.print(stack2); 10   } 11 12   public static    <T>    void   add(GenericStack  <T>  stack1, 13       GenericStack  <?   super   T>  stack2) { 14   while   (!stack1.isEmpty()) 15       stack2.push(stack1.pop()); 16   } 17 } 

The relationship among generic types and wildcard types is summarized in Figure 21.6. In this figure, A and B represent classes or interfaces, and E is a generic type parameter.


[Page 703]
Figure 21.6. The relationship between generic types and wildcard types.

 


Introduction to Java Programming-Comprehensive Version
Introduction to Java Programming-Comprehensive Version (6th Edition)
ISBN: B000ONFLUM
EAN: N/A
Year: 2004
Pages: 503

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