Hi all,
I am preparing for SCJP1.5 finding generics to be tough and a bit confusing.
Source: Kethy and Bates CD question.
Which of the following can be inserted at // Insert here.
1) public static <T> List <T>backwards ( List <T> input)
2) public static <T> List <T> backwards ( List <? extends T> input)
3) public static <T> List <T> backwards ( List <? super T> input)
4) public static <T> List <? extends T> backwards (List <T> input)
5) public static <T> List <? super T> backwards ( List <T> input)
6) public static <? extends T> List <T> backwards ( List <T> input)
Answer is : ABDE
not clear with the exact declaration syntax for Generics and how to use wildcards -extends and super in the above problem.
If anyone can help me , it will be great. Thanks in advance.
Ruben Soto
Ranch Hand
Joined: Dec 16, 2008
Posts: 1032
posted
0
Hi Pooja,
Let's look at the ones that are wrong (C. and F.)
C. public static <T> List <T> backwards ( List <? super T> input)
In this case, the parameter is declared as List <? super T>. The problem is that you are adding elements from input to output, which is declared as type List<T>. The real issue is that the actual type of the elements in input could be, for example, the direct superclass of T (let's call it Y), which could refer to actual objects of type X (another subclass of Y, unrelated with T.) Then, you can't add these elements to the list that holds elements of type T (output) because an X is not a T, so the compiler is stopping you from that possibility.
F. public static <? extends T> List <T> backwards ( List <T> input)
The problem in this case is that the syntax <? extends T> for the generic type declaration is incorrect. You can't have a wildcard (?) in the generic type declaration.
All code in my posts, unless a source is explicitly mentioned, is my own.
Punit Singh
Ranch Hand
Joined: Oct 16, 2008
Posts: 952
posted
0
Why C. option is invalid?
Here we have to ensure that input contains T or its subtype objects only, not other that that. Means we have to make T as upper bound of input.
And the problem is List<? super T> input.
See I what are assignable to this List<? super T> input.
You can see here List<? super T> input can contain any type of Objects in the java world, so it is not bounding T as upper bound.
Why B. option is valid?
here List<? extends T> input reference can only take reference of those list that are declared with generic parameter T or subtypes of T.
for ex:
Means here List<? extends T> input , limits the generic parameter of the assignable list means assignable list could be only List<? extends T>, List<T>, ArrayList<? extends T>, ArrayList<T>, LinkedList<? extends T>, LinkedList<T>, Vector<? extends T>, Vector<T>.
While it will not allow List<Object> references to be assigned to List<? extends T> reference.
Think in terms of what can be assigned to function argument List<? extends T> or List<? super T> or List<T> references. You will get the whole thing clear.
Here T is typed as 'Object'
But Object has no superclasses....so how could the List accept anything other than something that has been casted to object?
===>SCJP 1.5(72%)<===
==>SCWCD1.5(76%)<===
Punit Singh
Ranch Hand
Joined: Oct 16, 2008
Posts: 952
posted
0
List can accept anything that is Object or its subtypes.
Object is just upper bound here, you can insert its subtypes also.
So I can't add supertypes of T even though it says super?
Punit Singh
Ranch Hand
Joined: Oct 16, 2008
Posts: 952
posted
0
No you cannot add.
<? super T> is not designed for allowing objects that is supertype of T to be added in this.
The design purpose is actually for reference assignment.
Suppose you make a reference of List using <? super T>
Then <? super T> decides what could be assignable to this reference.
You can assign any reference that is supertype of T.
for example lets make one reference of a type that is supertype of T.
Now we can do this:
Ruben Soto
Ranch Hand
Joined: Dec 16, 2008
Posts: 1032
posted
0
Also, note that, to clarify things, the compiler is not thinking about what we are adding to what list. The error is caught at // 1 below, when you attempt to assign something that is probably of a supertype of T to a T reference variable:
But now I thought that the wildcard can't be used when declaring collections?
Punit Singh
Ranch Hand
Joined: Oct 16, 2008
Posts: 952
posted
0
No nothing like that wild cards cannot be used when defining collections.
John Grabowsky
Greenhorn
Joined: Dec 30, 2008
Posts: 26
posted
0
Hi all,
you can use wildcards in variable declarations and return type declarations, but not when creating an instance (new) or declaring a type parameter (as in answer F in the original question).
Forget, for the moment, the type parameter T and make clear easier things (if there are easy things with generics at all):
here a List<Number> can hold any subtypes of Number, so you can add anything that is a subtype of Number (line 1 fails, line 2 ok) and you can be sure to get anything that is a subtype of number (line 5 fails, lines 3+4 ok).
Now, use a wildcard in the declaration of l:
Now l can be any List with generic type ? super Number, i.e. a List<Number> or a List<Object> as line 0 shows. line 1-5 must work with ANY thing that l CAN be. When compiling line 1-5 the compiler knows only the declared type of l, not what is assigned to l. Thats why
line 1 fails, since l CAN be a List<Number> which cannot hold an Object
line 4 fails, since l CAN be a List<Object> and can deliver any Object
line 5 fails, since l CAN be a List<Object> or a List<Number> and can deliver in both cases things that are not Integers
Okay,so then
On the LHS: the reference types<generic declaration>defines what types can be referenced.
On the RHS:the <generic declaration> defines what can be stored in the collection.
John Grabowsky
Greenhorn
Joined: Dec 30, 2008
Posts: 26
posted
0
Yes. When using a reference variable declared with generics, as in line 1-5 above, you have to combine your 2 statements: What can be stored in types referenced by this reference variable. And your code must work with any possiby referenced type.
Punit Singh
Ranch Hand
Joined: Oct 16, 2008
Posts: 952
posted
0
Duran Harris wrote:Okay,so then
On the LHS: the reference types<generic declaration>defines what types can be referenced.
On the RHS:the <generic declaration> defines what can be stored in the collection.
Exactly Duran, you got a good point, your LHS RHS explains many things in just two lines, many rancher will get it very helpful. As generics are the most confusing topic and most asked questions.