Reputation: 575
Below is a question from Kathy & Bert Bates SCJP 5 preparation CD. I have posted this elsewhere too, but have not gotten a satisfactory explanation until now.... 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 at //Insert code here
?
public static <T> List<T> backwards(List<T> input)
public static <T> List<T> backwards(List<? extends T> input)
public static <T> List<T> backwards(List<? super T> input)
public static <T> List<? extends T> backwards(List<T> input)
public static <T> List<? super T> backwards(List<T> input)
public static <? extends T> List<T> backwards(List<T> input)
I understand that A and B are correct; however, not why are D and E also right. I can see that C and F are also incorrect. Can someone please tell me why D and E are correct.
Upvotes: 1
Views: 529
Reputation: 269857
Answer D, public static <T> List <? extends T> backwards(List <T> input)
, returns a list that can contain type T
or any of its subclasses. Since it can hold T
, it can hold any element in the input, and is "correct" in that sense.
Answer E, public static <T> List <? super T> backwards(List <T> input)
, is similar, but returns a list that can hold T
or any super class. Since it can also hold the input elements, it is also "correct."
Choosing one of these alternatives will impact what a user might expect to do with the resulting list.
With the List<? extends T>
output, one can iterate over the list and assign each element to a variable of type T
, but no elements, even of type T
, can be safely added to the List
. (Someone might be referring to this list as List<SubT>
, and would get a ClassCastException
when trying to retrieve the T
as a SubT
.)
With the List<? super T>
output, one can safely add elements to the List
if they are of type T
. However, an element from the list can only be safely assigned to a variable of type Object
. (Someone might be referring to this list as List<Object>
, and adding instances of Object
or other superclasses of T
).
With the List<T>
, one can safely assign the elements of the list to a variable of type T
, and can add elements of type T
to the list (assuming it's a modifiable List
implementation).
Upvotes: 2
Reputation: 192035
Because a List<T>
is a List<? extends T>
and 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 a supertype. Therefore, returning a List<T>
will satisfy both return types.
There are reasons for preferring to return one or the other, but the main point here is that they are legal.
Upvotes: 1