Two Laptop Bag*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Generics <?> Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Generics <?>" Watch "Generics <?>" New topic
Author

Generics <?>

Gil Steidle
Ranch Hand

Joined: Nov 19, 2010
Posts: 30
This abbreviated code is taken from a question in the SCJP 6 Study guide. My confusion is over what the <? super> is doing. From reading the book I (mis)understand that anything "higher" in the class heirachy should be allowed??? So, if we have class tree of: Fruit, Apple, Macintosh why can't I stick my Fruit into my List<? super Apple> list? Just the opposite is happening, I can put a Macintosh into the list even though the Macintosh is "lower" on the tree (no pun intended). I thought that List <? extends Apple> would allow this behavior? Code and output are below.


Thanks for your help with this,
Gil





Results:

C:\JAVA\SCJP\StudyGuide Exam>javac Macintosh.java
Macintosh.java:16: cannot find symbol
symbol : method add(Fruit)
location: interface java.util.List<capture#972 of ? super Apple>
list.add(new Fruit()); // No
^
1 error

C:\JAVA\SCJP\StudyGuide Exam>
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18914
    
  40


Basically, a List<? super Apple> is *not* a list that can take Apple, Fruit, and Object. It is either a List<Apple>, List<Fruit>, or List<Object>, but the compiler doesn't know which type it is. So, in order to add items to this unknown list, the compiler will only allow it, if it works regardless of which type, of the three options, it is.

This means that it will only allow you to add objects that IS-A Apple, IS-A Fruit, and IS-A Object. In this regard, Apple and Macintosh satisfy this requirement. A Fruit does not.

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18709
    
    8

A List<? super Apple> is a list of objects of some type which Apple extends. So for example if your Apple class implemented the Corporation interface, then that List could be a List<Corporation>. And clearly you couldn't add a Fruit object to that.

However you can add a Macintosh to the list because whatever type the ? happens to mean, Macintosh is guaranteed to be a subtype of it.
k reeta
Ranch Hand

Joined: Oct 15, 2010
Posts: 35
To add to the answers above, <? super apple> dictates the kind of argument(s) that you will be allowed to pass into the method in question (and not the type of objects that can be added via the add method, I think).

For instance, in this case you could call the method "basket" in the following ways -

(1) (The way you have done it)

List<Apple> a = new ArrayList<Apple>();
basket(a);

OR

(2) List<Fruit> f = new ArrayList<Fruit>();
basket(f);

since Fruit is higher in the hierarchy vis-a-vis apple.





Gil Steidle
Ranch Hand

Joined: Nov 19, 2010
Posts: 30
Ok, I think the light bulb is getting a little brighter. Thanks for responses. I tried flipping the logic and used "extends" in place of "super" to get the classes Apple or lower. This doesn't work. I thought it would. What am I still missing?

New code and results...




C:\JAVA\SCJP\StudyGuide Exam>javac Macintosh.java
Macintosh.java:17: cannot find symbol
symbol : method add(Apple)
location: interface java.util.List<capture#28 of ? extends Apple>
list.add(new Apple()); // NO, now it does not work with extends
^
1 error

C:\JAVA\SCJP\StudyGuide Exam>
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18914
    
  40

Gil Steidle wrote:I tried flipping the logic and used "extends" in place of "super" to get the classes Apple or lower. This doesn't work. I thought it would. What am I still missing?


A slight modification of my last response....

Basically, a List<? extends Apple> is *not* a list that can take Apple, Macintosh, or anything that IS-A Apple. It is either a List<Apple>, List<Macintosh>, or List<GrannySmith>, etc. etc., but the compiler doesn't know which type it is. So, in order to add items to this unknown list, the compiler will only allow it, if it works regardless of which type, of the many possible options, it is.

This means that it will only allow you to add objects that IS-A Apple, IS-A Macintosh, IS-A GrannySmith, and IS-A anything else that IS-A Apple. In this regard, there are no object type that fulfills this request. The only possible item that can be added, because it can be assigned to all of those reference types, is null.

Henry
Gil Steidle
Ranch Hand

Joined: Nov 19, 2010
Posts: 30
This means that it will only allow you to add objects that IS-A Apple, IS-A Macintosh, IS-A GrannySmith, and IS-A anything else that IS-A Apple.


Does this mean...

This means that it will only allow you to add objects that IS-A Apple, AND IS-A Macintosh, AND IS-A GrannySmith, AND IS-A anything else that IS-A Apple?

Given the current code no class meets that criteria, is that how you got to...

The only possible item that can be added, because it can be assigned to all of those reference types, is null.


If I'm following you then I would need to generalize the method's add to accept any Type that is allowed. I changed the method to this



Unsuccessful. Help.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18914
    
  40

Gil Steidle wrote:


Unsuccessful. Help.


You can't instantiate a generic type. And there is no work around. You can't add anything to a List<? extends Apple> except null.

Henry
Gil Steidle
Ranch Hand

Joined: Nov 19, 2010
Posts: 30
How should I approach solving this puzzle of being able to use an Apple or Macintosh or Red Delicous or maybe an Orange Fruit list?
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18709
    
    8

What puzzle is that? Originally you were just asking about a problem on a test.

If you want a List which can contain anything which is a subclass of Fruit, then List<Fruit> is what you want. You can add any Fruit to that.
Gil Steidle
Ranch Hand

Joined: Nov 19, 2010
Posts: 30
Sorry, but I can't seen to wrap my brain around this concept yet. In the code example below is my confusion.

Gil Steidle
Ranch Hand

Joined: Nov 19, 2010
Posts: 30
Here's the semi-colon that is missing ;
Paul Anilprem
Enthuware Software Support
Ranch Hand

Joined: Sep 23, 2000
Posts: 3315
    
    8
I think you are over complicating it in your mind. It is quite simple actually, if you understand the following three basic principles:

1. The whole (ok, not whole but one of the main) purpose of having generics is to avoid putting random things in any collection. After all, you want things organized. You don't want to put apples in a sack of potatos. And when you are given a sack of apples, you expect apples to come out and not potatos. As the same time, if you are given a "basket of fruit" as a gift, you should be able to put an orange, an apple, a mcintosh apple, or any other fruit into it. Right? And when you pick a fruit from that basket, do you always expect to get an apple? No, right?

That's the fundamental thing and the hardest to absorb (I bet you are rolling your eyes ).

Now, the simpler stuff:

2. ? extends Apple : This means "of a class that extends Apple". Therefore, List<? extends Apple> means a sack of some variety of Apple. Mcintosh? Probably. But you don't know.

Q. So when you are given a sack of "? extends Apple", can you put a Mcintosh in it? If you have any doubt, read point 1 again. (Hint: Do you want to mess up your sack of Fuji apples by putting a Mcintosh apple it it?)
Q. So when you take out stuff from a sack of "? extends Apple", what do you get? An Apple for sure. (You don't mind if it is a Mcintosh or a Fuji, do you? As long as you don't get a Potato, you are good )

3. ? super Apple: This means "of a class that is a super class of Apple". Therefore, List<? extends Apple> means a sack of something of which an Apple is a kind. Let's call it "it". Now play Jeopardy. So, What do you call a sack of something of which an Apple is a kind? A sack of fruits. Are you sure? Can you not call it a sack of food items? or A sack of Mcintoshes? (Hint: Every apple is a kind of fruit. Every apple is a kind of food item. Is every apple a kind of Mcintosh?) So which of these statements should work?

listOfsuperApple.add(anApple);
listOfsuperApple.add(someFruit);
listOfsuperApple.add(aMac);

Read 1 again, if in doubt.

Q. So when you take out stuff from a sack of "? super Apple", what do you get? Apple? Probably. A fruit? probably. Some food item? probably. Are you sure? No. So what are you sure of? Well, its something, but you don't know what. So you are sure of nothing, really. So which of these statements should work?

Apple a = listOfsuperApple.get(0);
Fruit a = listOfsuperApple.get(0);
FoodItem a = listOfsuperApple.get(0);
Object a = listOfsuperApple.get(0);

Read 1 again, if in doubt.

Q. So when you are given a sack of "it", can you put any apple in it? Well, can you not put any apple in a sack of fruits? in a sack of food items? In a sack of apples?

Read 1 again, if in doubt.


That's it! If you understand point 1, you will never miss any question on generics. Ever!

Quiz: What would List<?> mean? What can you put in it and what can you take out from it?






Enthuware - Best Mock Exams and Questions for Oracle/Sun Java Certifications
Quality Guaranteed - Pass or Full Refund!
Paul Anilprem
Enthuware Software Support
Ranch Hand

Joined: Sep 23, 2000
Posts: 3315
    
    8

List<? super Apple> b // Declare a List that will accept a List higher than Apple
b = new ArrayList<Fruit>(); // Give it a List<Fruit>
//b.add(new Fruit()); // Try to add a Fruit object to a List<Fruit> fails, why???


Hint 1: It has nothing to do with generics!

Hint 2:

Fruit f = null;
f = new Apple();
f.methodOfClassApple(); //fails!
((Apple) f).methodOfClassApple(); //works!
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18914
    
  40

Paul Anilprem wrote:I think you are over complicating it in your mind. It is quite simple actually, if you understand the following three basic principles:


Agreed. And I really like the explanation. Nice examples.... but I also think that maybe the OP may be using wildcards where it is not needed.

Paul Clapham wrote:
If you want a List which can contain anything which is a subclass of Fruit, then List<Fruit> is what you want. You can add any Fruit to that.


Agreed. If the task is to work with a container that can take any type of fruit, then it should be a List<Fruit> -- and no wildcards needed. I guess the next step is for Gil to explain the use case in question.

Henry
Gil Steidle
Ranch Hand

Joined: Nov 19, 2010
Posts: 30
Paul, thank you for your thorough explanation. I appreciate it.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Generics <?>