Perplexity of generics
Below is a question from Katy and Bert Bates's SCJP 5 training CD. I've also posted this elsewhere but still haven't gotten a satisfactory explanation. Please help me understand this:
public class BackLister {
//Insert code here
{
List<T> output=new LinkedList<T>();
for(T t:input)
output.add(0,t);
return output;
}
}
Which of the following can be inserted into //Insert code here
?
- A .
public static <T> List<T> backwards(List<T> input)
- In .
public static <T> List<T> backwards(List<? extends T> input)
- The C .
public static <T> List<T> backwards(List<? super T> input)
- D .
public static <T> List<? extends T> backwards(List<T> input)
- E .
public static <T> List<? super T> backwards(List<T> input)
- The F .
public static <? extends T> List<T> backwards(List<T> input)
I understand that A and B are correct; however, not why D and E are also right. I see that C and F are also wrong. Can someone please tell me why D and E are correct.
a source to share
Answer D,, public static <T> List <? extends T> backwards(List <T> input)
returns a list, which can contain the type T
or any of its subclasses. Since it can contain T
, it can hold any element in the input, and is "correct" in that sense.
Answer E,, is public static <T> List <? super T> backwards(List <T> input)
similar, but returns a list, which can contain T
or any superclass. Since it can also contain input elements, it is also "correct".
Choosing one of these alternatives will affect what the user can expect from the resulting list.
-
With the output,
List<? extends T>
it is possible to iterate over the list and assign each element to a variable of typeT
, but no elements, not even the typeT
, can be safely added toList
. (Someone might refer to this list asList<SubT>
and will receiveClassCastException
when trying to getT
howSubT
.) -
With the exit,
List<? super T>
it is safe to add elements toList
if they are of typeT
. However, an item from a list can only be safely assigned to a variable of typeObject
. (Someone might refer to this list likeList<Object>
adding instancesObject
or other superclassesT
). -
Using,
List<T>
you can safely assign list items to a type variableT
and add type items to the listT
(assuming this is a modifiableList
implementation).
a source to share
Since a List<T>
is List<? extends T>
also a List<? super T>
, by definition. ? extends T
is a wildcard indicating T
or a subtype, and ? super T
is a wildcard indicating T
or supertype. Therefore, returning a List<T>
will satisfy both return types.
There are reasons to choose to return one or the other, but most importantly, they are legal.
a source to share