Wildcards in Generics

In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific). The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype.



Upper Bounded Wildcards:


You can use an upper bounded wildcard to relax the restrictions on a variable. For example, say you want to write a method that works on List<Integer>List<Double>,and List<Number>; you can achieve this by using an upper bounded wildcard.
To declare an upper-bounded wildcard, use the wildcard character ('?'), followed by the extends keyword, followed by its upper bound. Note that, in this context, extends is used in a  sense to mean either "extends" (as in classes) or "implements" (as in interfaces). To write the method that works on lists of Number and the sub-types of Number, such as IntegerDouble, and Float, you would specify List<? extends Number>. The term List<Number> is more restrictive than List<? extends Number> because the former matches a list of type Number only, whereas the latter matches a list of type Number or any of its subclasses.

Consider the following process method:

public static void process(List<? extends Test> list) { /* ... */ }

The upper bounded wildcard, <? extends Test>, where Test is any type, matches Test and any subtype of Test. The process method can access the list elements as type Test:
public static void process(List<? extends Test> list) {
    for (Test var : list) {
        // ...
    }
}




Unbounded Wildcards:

The unbounded wildcard type is specified using the wildcard character (?), for example, List<?>. This is called a list of unknown type. There are two scenarios where an unbounded wildcard is a useful approach:
  • If you are writing a method that can be implemented using functionality provided in the Object class.
  • When the code is using methods in the generic class that don't depend on the type parameter. For example, List.size or List.clear. In fact, Class<?> is so often used because most of the methods in Class<T> do not depend on T.



Consider the following method, printList:


public static void printList(List<Object> list) {
    for (Object elem : list)
        System.out.println(elem + " ");
    System.out.println();
}



The goal of printList is to print a list of any type, but it fails to achieve that goal — it prints only a list of Object instances; it cannot print List<Integer>List<String>,List<Double>, and so on, because they are not subtypes of List<Object>.



 To write a generic printList method, use List<?>:




public static void printList(List<?> list) {
    for (Object elem: list)
        System.out.print(elem + " ");
    System.out.println();
}




It's important to note that List<Object> and List<?> are not the same. You can insert an Object, or any subtype of Object, into a List<Object>. But you can only insert null into a List<?>.












0 comments:

Post a Comment

 
Copyright (c) 2013 Java Discovery.