Wildcards


Sometimes you'll write a method where you don't care about the type to which a parameter is bound. Suppose you need a utility method that creates a single string by concatenating elements in a list, separating the printable representation of each element with a new line. The StringUtilTest method testConcatenateList demonstrates this need:

 package sis.util; import junit.framework.*; import java.util.*; public class StringUtilTest extends TestCase {    ...    public void testConcatenateList() {       List<String> list = new ArrayList<String>();       list.add("a");       list.add("b");       String output = StringUtil.concatenate(list);       assertEquals(String.format("a%nb%n"), output);    } } 

In the StringUtil method concatenate, you will append each list element's string representation to a StringBuilder. You can get the string representation of any object, provided by the toString method, without knowing or caring about its type. Thus, you want to be able to pass a List that is bound to any type as the argument to concatenate.

You might think that you can bind the list parameter to Object:

 // this won't work public static String concatenate(List<Object> list) {    StringBuilder builder = new StringBuilder();    for (Object element: list)       builder.append(String.format("%s%n", element));    return builder.toString(); } 

By binding list to Object, you constrain it to hold objects only of type Objectand not of any Object subclasses. You cannot assign a List<String> reference to a List<Object> reference. If you could, client code could add an Object to list using the List<Object> reference. Code that then attempted to extract from list using the List<String> reference would unexpectedly retrieve an Object.

Instead, Java allows you to use a wildcard character (?) to represent any possible type:

 package sis.util; import java.util.*; public class StringUtil {    ...    public static String concatenate(List<?> list) {       StringBuilder builder = new StringBuilder();       for (Object element: list)          builder.append(String.format("%s%n", element));       return builder.toString();    } } 

Within the concatenate method body, you cannot use the ? directly as a naked type variable. But since list can contain any type of object, you can assign each of its elements to an Object reference in the for-each loop.

Additionally, you can constrain a wildcard to an upper bound using the extends clause.

For a second string utility method, you need to be able to concatenate a list of numerics, whether they are BigDecimal objects or Integer objects. Several tests drive out the minor differences between decimal output and integral output:


 public void testConcatenateFormattedDecimals() {    List<BigDecimal> list = new ArrayList<BigDecimal>();    list.add(new BigDecimal("3.1416"));    list.add(new BigDecimal("-1.4142"));    String output = StringUtil.concatenateNumbers(list, 3);    assertEquals(String.format("3.142%n-1.414%n"), output); } public void testConcatenateFormattedIntegers() {    List<Integer> list = new ArrayList<Integer>();    list.add(12);    list.add(17);    String output = StringUtil.concatenateNumbers(list, 0);    assertEquals(String.format("12%n17%n"), output); } 

The implementation in StringUtil:

 public static String concatenateNumbers(       List<? extends Number> list, int decimalPlaces) {    String decimalFormat = "%." + decimalPlaces + "f";    StringBuilder builder = new StringBuilder();    for (Number element: list) {       double value = element.doubleValue();       builder.append(String.format(decimalFormat + "%n", value));    }    return builder.toString(); } 

You'll need to import java.math.* to get the above code to compile.

The declaration of the list parameter in concatenateNumbers specifies that it is a List bound to either Number or a subclass of Number. The code in concatenateNumbers can then assign each element in list to a Number reference.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

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