• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Generics <?>

 
Ranch Hand
Posts: 30
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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>
 
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
 
Sheriff
Posts: 28324
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 30
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 30
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 30
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Sheriff
Posts: 28324
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 30
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 30
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here's the semi-colon that is missing ;
 
Enthuware Software Support
Posts: 4884
60
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?





 
Paul Anilprem
Enthuware Software Support
Posts: 4884
60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


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
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 30
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Paul, thank you for your thorough explanation. I appreciate it.
 
I have gone to look for myself. If I should return before I get back, keep me here with this tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic