aspose file tools*
The moose likes Beginning Java and the fly likes How to interpret Generics using wildcard and type parameters Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "How to interpret Generics using wildcard and type parameters" Watch "How to interpret Generics using wildcard and type parameters" New topic
Author

How to interpret Generics using wildcard and type parameters

Abhi Bhutani
Greenhorn

Joined: Aug 26, 2008
Posts: 8
Hi I have read generics quiet a few times but i still get completely bowled over when i see a question that uses wildcards, type parameter all together. I am unable to interpret the code properly. So please see the question and the answer below (this is from KB book for SCJP 5), and try to explain me.


import java.util.*;
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 to compile and run without error ?

A. public static<T> List<T> backwards(List<T> input)
B. public static<T> List<T> backwards(List<? extends T> input)
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 correct answers are A, B, D, E. Only C is incorrect

For explanation purposes if you wish you could use the classes mentioned below:

class A.
Class B extends A.
class C extends B.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39396
    
  28
I presume you have found the Java Tutorials about generics and Angelika Langer's generics FAQ? What does it say in the K&B book about that question?

Please show us what you think so far; we believe you will learn better than if we simply tell you the answer. It is actually not a particularly difficult question.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

I think it would help you understand if you substitute a class name for the generics and try to understand the consequences. So for example,

Class Dog
Class Terrier extends Dog
Class MiniTerrier extends Terrier

Then, for each answer replace the Generics with the appropriate class name.
For T => Terrier:
A. public static<Terrier> List<Terrier> backwards(List<Terrier> input)
B. public static<Terrier> List<Terrier> backwards(List<MiniTerrier> input)
etc...

It may come out as more obvious why C is wrong and the others are not.


Steve
Abhi Bhutani
Greenhorn

Joined: Aug 26, 2008
Posts: 8
I have read Java tutorial on Generics. However i am going to check out Angelika FAQ's. In the meantime this is what i understood about this question so far.

According to the book it says the best way to understand the use of type parameters is to mentally replace every occurence of the parameter type in the code with the type with which you are going to invoke the method. On that basis:

List<A> a = new ArrayList<A>();
List<B> b = new ArrayList<B>();
List<C> c = new ArrayList<C>();

1. public static<T> List<T> backwards(List<T> input)
backwards(a) or backwards(b) or backwards(c) are all correct invocations as in this case in the bytecode T is simply replaced by the class name i.e A, B or C. So this is fine.

2. public static<T> List<T> backwards(List<? extends T> input)
In this case i feel "? extends" is redundant because if i invoke method like backwards(a), then in the bytecode T is replaced by class A, then what is the use of "? extends" part.

3. public static<T> List<T> backwards(List<? super T> input)
Similarly to point 2, i feel the use of "? super" is redundant.

4. public static<T> List<? extends T> backwards(List<T> input)
Now if i invoke backwards(b), then in bytecode, T is replaced by class B, then how am i ever going to return a List or ArrayList of subtype of class B.

5. public static<T> List<? super T> backwards(List<T> input)
Same as 4, if i invoke backwards(b) how am i ever going to return a List of supertype of class B
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39396
    
  28
Originally posted by Abhi Bhutani:
5. public static<T> List<? super T> backwards(List<T> input)
Same as 4, if i invoke backwards(b) how am i ever going to return a List of supertype of class B
For this purpose, regard ? super B as including B, so call B a "supertype" of itself.
Abhi Bhutani
Greenhorn

Joined: Aug 26, 2008
Posts: 8
Hi Steve,

Ignore option A for the moment. Just think of option B.
If I invoked backwards(List<MiniTerrier>) then result will be:

B. public static<MiniTerrier> List<MiniTerrier> backwards(List<? extends MiniTerrier> input)

in other words now T will be replaced by MiniTerrier? isn't it ?

[edit]Disable smilies. CR[/edit]
[ September 28, 2008: Message edited by: Campbell Ritchie ]
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39396
    
  28
You say something in redundant in no 2, then you say something is redundant in no 3. Are you quite sure you know what redundant means? It implies more than is required, but does not imply incorrectness; you have already seen that no 2 was called "correct" and no 3 was called "incorrect," so "redundant" is probably not the right word to use for one of them.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

Originally posted by Abhi Bhutani:
Hi Steve,

Ignore option A for the moment. Just think of option B.
If I invoked backwards(List<MiniTerrier>) then result will be:

B. public static<MiniTerrier> List<MiniTerrier> backwards(List<? extends MiniTerrier> input)

in other words now T will be replaced by MiniTerrier? isn't it ?

[edit]Disable smilies. CR[/edit]

[ September 28, 2008: Message edited by: Campbell Ritchie ]


Yes, in that specific case, we are trying to understand the generic case, so lets keep with Terrier since we know something about its children...

Let's expand our class family a bit.

Class Dog
Class Shepherd extends Dog
Class GermanShepherd extends Shepherd
Class AnatolianShepherd extends Shepherd
Class Terrier extends Dog
Class MiniTerrier extends Terrier
Class Yorkie extends Terrier

When you have a List<? extends Terrier> what objects can you put in the List?
When you have a List<Terrier> what objects can you put in the List?
When you have a List<? super Terrier> what objects can you put in the List?

Then:
When you have a List<? extends Terrier> what kind of Lists can you pass to the method?
When you have a List<Terrier> what kind of Lists can you pass to the method?
When you have a List<? super Terrier> what kind of Lists can you pass to the method?

Finally for each of the above, what types of Objects can you safely pull out of the List, so that you can modify it or put it in another list? (safely means without having to cast or use instanceof)
Abhi Bhutani
Greenhorn

Joined: Aug 26, 2008
Posts: 8
Originally posted by Steve Luke:


Yes, in that specific case, we are trying to understand the generic case, so lets keep with Terrier since we know something about its children...

Let's expand our class family a bit.

Class Dog
Class Shepherd extends Dog
Class GermanShepherd extends Shepherd
Class AnatolianShepherd extends Shepherd
Class Terrier extends Dog
Class MiniTerrier extends Terrier
Class Yorkie extends Terrier

When you have a List<? extends Terrier> what objects can you put in the List?
When you have a List<Terrier> what objects can you put in the List?
When you have a List<? super Terrier> what objects can you put in the List?

Then:
When you have a List<? extends Terrier> what kind of Lists can you pass to the method?
When you have a List<Terrier> what kind of Lists can you pass to the method?
When you have a List<? super Terrier> what kind of Lists can you pass to the method?

Finally for each of the above, what types of Objects can you safely pull out of the List, so that you can modify it or put it in another list? (safely means without having to cast or use instanceof)


Answers to your questions:
1.When you have a List<? extends Terrier> what objects can you put in the List?

You can put Terrier, MniTerrier and Yorkie

2. When you have a List<Terrier> what objects can you put in the List?

Same as 1.

3. When you have a List<? super Terrier> what objects can you put in the List?

Terrier or a Dog

4. When you have a List<? extends Terrier> what kind of Lists can you pass to the method?

I can pass List<Terrier> or any of the List<subtypes of Terrier>

5. When you have a List<Terrier> what kind of Lists can you pass to the method?

I can only pass List<Terrier>

6. When you have a List<? super Terrier> what kind of Lists can you pass to the method?

I can pass List<Terrier> or List<Dog>
Abhi Bhutani
Greenhorn

Joined: Aug 26, 2008
Posts: 8
I am still very confused and trying to see if i can make sense of this after Angelika's Generics website.
Steven Rodeo
Ranch Hand

Joined: Mar 06, 2008
Posts: 72
Try this. hopefully this will clear up your head.




-------------------------------------------------------------------------
-------------------------------------------------------------------------
-------------------------------------------------------------------------



-D

[edit]Add code tags. CR[/edit]
[ November 07, 2008: Message edited by: Campbell Ritchie ]
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39396
    
  28
Please always use the code button; code is difficult to read without it. And I am afraid it probably is too late for your post to be helpful. Please look at this FAQ.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: How to interpret Generics using wildcard and type parameters