• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Genrecis and Wildcard

 
Pooja Desai
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 1032
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Punit Singh
Ranch Hand
Posts: 952
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


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.

Option F is already well said by Ruben.
 
Jesper de Jong
Java Cowboy
Saloon Keeper
Posts: 15627
46
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to JavaRanch. Please use code tags when you post source code.
 
Duran Harris
Ranch Hand
Posts: 608
Eclipse IDE Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Punit

You said for the following:

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?
 
Punit Singh
Ranch Hand
Posts: 952
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
List can accept anything that is Object or its subtypes.



Object is just upper bound here, you can insert its subtypes also.
 
Duran Harris
Ranch Hand
Posts: 608
Eclipse IDE Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Okay...

then what is the point of using something like:

because then you can insert anything...?

and

would be the same as just:


 
Punit Singh
Ranch Hand
Posts: 952
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


Here you can add T objects and its subtypes objects.


Here you can't add anything.


Here you can add T objects and its subtypes objects.
 
Duran Harris
Ranch Hand
Posts: 608
Eclipse IDE Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

So I can't add supertypes of T even though it says super?
 
Punit Singh
Ranch Hand
Posts: 952
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 1032
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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:

 
Duran Harris
Ranch Hand
Posts: 608
Eclipse IDE Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Punit


But now I thought that the wildcard can't be used when declaring collections?
 
Punit Singh
Ranch Hand
Posts: 952
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No nothing like that wild cards cannot be used when defining collections.


 
John Grabowsky
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
  • lines 2+3 ok

  •  
    Duran Harris
    Ranch Hand
    Posts: 608
    Eclipse IDE Spring Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    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
    Posts: 26
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    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
    Posts: 952
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    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.
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic