• 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
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Generic methods and wildcards

 
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

This is an extrace of the guide published in: http://java.boot.by/scjp-tiger/ch06s04.html

"As an example of using wildcards, consider a draw() method that should be capable of drawing any shape such as circle, rectangle, and triangle. The implementation may look something like this. Here Shape is an abstract class with three subclasses: Circle, Rectangle, and Triangle:




It is worth noting that the draw(...) method can only be called on lists of Shape and cannot be called on a list of Circle, Rectangle, and Triangle for example. In order to have the method accept any kind of shape, it should be written as follows:


"

When I tried this, providing Shape isn't an abstract class, both draw functions behaved exactly the same.

Could anyone explain, why it is expected that they would not. particularily I am not clear about the statment in bold.

Thanks
Katrin
 
Ranch Hand
Posts: 262
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hi !!!

? estends Shape means: The class Shape or any subclass of Shape.

Calling the two methods with a Shape instance will have the same result.

Note that a List<Rectangle> is not a List<Shape> even if a Rectangle is a Shape.

You cannot call the method draw(List<Shape> shape) with a list of Rectangle List<Rectangle>. The following code will not compile


But you can call the method draw(list< ? extends Shape> shape) with a list of any subclass of a Shape
You can call the method with a List<Rectangle>. The following code will compile.



Hope i clear your doubt.
[ September 15, 2007: Message edited by: Collins Mbianda ]
 
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Howdy all,

I'm having trouble with Generics too, so instead of creating a similiar topic, I shall post my problems here.

Given :



For #1,#2,#3 and #4, my doubts are why the List< ? super A > was able to add a B inside. Is it because it is allowed for any subtype of A to be added too? Also, #4 gives a COMPILATION error !! Why? Doesnt A extends Object? Object is a superclass of A.

For #5 and #6, the list was specified as <? extends A>, means ANYTHING which is A or subclass of A can be added. But how come when I add a A , it refuses to compile?


Hope to get cleared here. My exam's less than 2 days time. I'm really getting nervous. Haha.

[ September 15, 2007: Message edited by: Brandon Bay ]
[ September 15, 2007: Message edited by: Brandon Bay ]
 
Collins Mbianda
Ranch Hand
Posts: 262
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi!!!



From K&B Book(page 593) :

By List<? extends Animal> we're saying: " I can be assigned a collection that a subtype of List and typed for<Animal> or anything extends Animal. And oh yes, I SWEAR that will not ADD anything into the collection."


For that reason you cannot add an element to your list:


You will get a compile error at #6.

When you use the < ? super ...> syntax, you are telling the compiler that you can accept the type on the right hand side of super or any of it supertypes,


new A() is an instance of A. That why #2 compile.
new B() is an instance of A since B extends A. That why #3 compile.
new Object() is not an instance of A. That why #4 don't compile.

Hope i clear your doubt.
Good luck for the exam.
[ September 15, 2007: Message edited by: Collins Mbianda ]
 
Brandon Bay
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i see.. thanks for your feedback and well wishes Collins
 
Katrin Perry
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you it is a lot clearer now. I have my test in 4 days.
Katrin
 
Collins Mbianda
Ranch Hand
Posts: 262
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Good luck to both of you.
 
Ranch Hand
Posts: 1274
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry, is a bit long...

To Katrin:

On the other hand, you can use the method as it is with List<Shape>.
There is no problem to stuck a (e.g.) Triangle into this list, because a Triangle IS-A Shape (and has got the draw() method).

The extended version is only needed if you really have to deal with pure lists of Triangle, Rectangle, Circle.



Katrin:


When I tried this, providing Shape isn't an abstract class, both draw functions behaved exactly the same.


They are not the same, as Collins already explained.
I don't know why you don't want Shape to be abstract. Should work fine as well.

To explain:
Just for drawing Circles, Rects etc. you do NOT need a List<? extends Shape>.
A List<Shape> should be enough:

prints a lot of circles, rectangles and triangles.


Only when you e.g. have a method that returns a List<Triangle> then the drawAll does not work.
Then you would either stuff the List<Circle> into a new List<Shape> or use the "extended version":

This will compile without warnings and prints rects and tris twice.


Yours,
Bu.
 
Burkhard Hassel
Ranch Hand
Posts: 1274
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To Brandon:

What Collins wrote can be a bit misleading:

When you use the < ? super ...> syntax, you are telling the compiler that you can accept the type on the right hand side of super or any of it supertypes, ...




If Collins were right, you would be able to add and Object() into such a list, because Object is the supertype of everything. But you can't.


So generally:
List<? extends YourClass> variable;
You can assign a list of anything that extends YourClass (and YourClass itself) to this variable.
You can add nothing to that class. Is read-only. Exception: you can add null.

List<? super YourClass> variable;
You can assign a list of YourClass or anything higher in hierarchy (including List<Object> to this variable.

Assigning a list higher in hierarchy also means, that this list may already contain objects higher in hierarchy without problems.
You can also add objects (small o) of type MyClass to this list.
But: You can not add objects higher than type "YourClass" to this list directly.
And: What you get out of this list is of type Object, not YourClass.

prints something like [java.lang.Object@10b62c9, a String, null].

Of course you can add "lower" types to this kind of lists cause for any Collection<MyClass> you can add subclasses of MyClass. The object behind can surely be lower, because of polymorphy the same as when you can e.g. say:
Object x = new Integer(5);






To all:
Good luck!


Yours,
Bu.
 
Katrin Perry
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Burkhard,

I am now a bit confused with your explanations to Brandon.

Why in the last code example:



wouldn't compile? I mean, I tried it and it really doesn't

I am just not clear at all why.

Great explanation to my Generics problem, thanks.


Brandon good luck to you!
 
Burkhard Hassel
Ranch Hand
Posts: 1274
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You are absolutely right, this is puzzling.


List<Object> objList = new ArrayList<Object>();
objList.add(new Object());

List<? super String> superList = objList; // fine


This <? super String> can be referred to Lists of String and all the hierarchy up to Object (ok, there is only class Object higher than String because String extends Object directly). As in the example, the superList can contain also Objects.
You can also code:
List<? super String> superList = new Vector<Object>();

In the upper example, the array list already contained an Object (big O), but that is ok since what you get out of that list will always be of type Object (not String!).


A List<? super String> may contain lists of type String and any higher type.
But you can add directly only Strings, nothing higher.
These difference is what puzzles people.





This has to be that way.
When you have a



you are allowed to assign two kinds of lists to it:
List<String> or List<Object>. (ok, not Lists themself, cause they are interfaces and can't be instanciated).

The compiler has to assure, that you add only things that fit in.
It does not know, if you later assign a List<String> or a List<Object> to that variable.
Therefore it allows only to add directly the highest type possible of the lowest type a list can have that is referred by this variable.
Lowest type possible is String, therefore only Strings can be allowed to be added directly.
But the lists assigned to that variable can be Strings or higher.


Phew.

Yours,
Bu.
 
Collins Mbianda
Ranch Hand
Posts: 262
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Burkhard for all these explanations.
We were making confusion on how to insert elements within
a List< ? super ...>

We will remenber what you say:

A List<? super String> may contain lists of type String and any higher type.
But you can add directly only Strings, nothing higher.

 
Katrin Perry
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks I would try to remember.
reply
    Bookmark Topic Watch Topic
  • New Topic