I have this bit of ( counter-intuitive ) observations about generic wildcard notation used in collections.
The purpose of the wildcard notation List<? extends T>
is to allow the assignment of a List (of subtypes of T) to the reference of List of '? of T'. Its purpose is not to specifically allow the adding of elements of subtypes of T into the List ( of '? of T' ) , which is possible even in a List<T>
.
List<Number> list = new ArrayList<Integer>(); // invalid , List<Integer> is not assignable to List<Number>
List<Number> list = new ArrayList<Number>() ; // OK
list.add(new Integer(1)); // valid , '? extends Number' not needed!
List<? extends Number> list1 = new ArrayList<Integer>(); // Valid , because of notation '? extends Number'
Is my observation correct ?
These wildcards can be used when you want 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 do this using an upper bounded wildcard. To declare an upper-bounded wildcard, use the wildcard character ('?
super T denotes an unknown type that is a supertype of T (or T itself; remember that the supertype relation is reflexive). It is the dual of the bounded wildcards we've been using, where we use ? extends T to denote an unknown type that is a subtype of T .
extends Number> represents a list of Number or its sub-types such as Integer and Double. Lower Bounded Wildcards: List<? super Integer> represents a list of Integer or its super-types Number and Object.
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).
Yes, your observation is correct. However, in the case you show, it's not very useful (you're electing to ignore useful information about the list). The assignment is more useful when it's implicit as you call a library function.
For example, say you had a library function that closed a collection of InputStreams. You could accept a List<InputStream>
, but that is unnecessarily restrictive. You could instead do this:
public void closeAll(Collection<? extends InputStream> streams) {
for ( InputStream stream : streams ) {
stream.close();
}
}
Now you can pass in a List<FileInputStream>
instead.
Extends is for reading from a list , and Super is for writing to a list. Read page 7 of this tutorial : http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf
Read these lecture notes from MIT class in software construction: http://stellar.mit.edu/S/course/6/sp11/6.005/courseMaterial/topics/topic2/lectureNotes/Generics-spring11/Generics-spring11.pdf
hopefully these will make everything clear with wildcards and generics.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With