• 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

Java collection

 
Ranch Hand
Posts: 348
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
after discussing about generics, I tried it for a bit to refresh my memory, and then I realized, apparently I haven't fully mastered this feature. there are several construct that I haven't seen before. I read Java tutorial docs in oracle about this subject, but I still have some blind spot.


so :
1. in this declaration, what should I put in the arraylist's bracket? any type that's a subclass or A or does it have to be A and only A? and what if it's a lower bound being used on the left hand side?
2. in this upper bound wildcard, I can't add any item to the collection, even when it's of type A. why is this? what scenario is this constraint trying to prevent?
3. if I use ? super A, then list can be populated only with item of type A or its subclasses (rather contradictive with the "super" bound). why is this?

Thanks
 
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Spades wrote:1. in this declaration, what should I put in the arraylist's bracket? any type that's a subclass or A or does it have to be A and only A?


The first (A or a subclass).

2. in this upper bound wildcard, I can't add any item to the collection, even when it's of type A. why is this? what scenario is this constraint trying to prevent?


Simply put: misuse.

People often misunderstand what the "?" in "? extends" means: It does NOT mean "anything", it means "an unknown type", so the declaration:
List<? extends Fruit>
means "a List of an unknown type that extends (or is a) Fruit".

Therefore, the assignment could be:
List<? extends Fruit> fruits = new ArrayList<Fruit>();
or:
List<? extends Fruit> fruits = new ArrayList<Apple>();
or:
List<? extends Fruit> fruits = new ArrayList<Orange>();
but the minute you use the reference 'fruits', the compiler doesn't know the actual type of the List. Therefore it can't allow you add anything to it, because it doesn't know whether what you're adding (even if it's a Fruit) is the right type for the List.

3. if I use ? super A, then list can be populated only with item of type A or its subclasses (rather contradictive with the "super" bound). why is this?


Basically, for the same reason as above:
List<? super Orange>
means "a List of an unknown type that is a superclass of (or is an) Orange".

So any of the following assignments are fine:
List<? super Orange> fruits = new ArrayList<Orange>();
List<? super Orange> fruits = new ArrayList<Fruit>();
List<? super Orange> fruits = new ArrayList<Object>();
but this one isn't:
List<? super Orange> fruits = new ArrayList<SeedlessOrange>();

So even though the actual type of 'fruits' is not known, in this case the compiler DOES know that it must be one that can take an Orange or a subclass.

Hope it helps.

Winston
 
David Spades
Ranch Hand
Posts: 348
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
1. so basically, the bracket on the right hand side can be filled with any type that satisfies the wildcard on the left hand side?
2. what are the effects on the type chosen for the right hand side? lets say A has 3 levels deeps of inheritance A->B->C->D, what effect does choosing B,C or D for the right hand side?
3. I thought when using upper bound, all the items extracted from the collection would automatically be cast to the upper bound type?
4. also, when using lower bound, items can be added with no problem, but the items added can only be subclasses (instead of superclass) of the lower bound (seems like counter intuitive)?
5. I tried the following:

Class hierarchy is A->B->C
my question is, when extracting the items out of listA, how does the compiler know what methods available for the extracted item? if it's upper bound, you can use the assumption that all items are cast as the upper bound, so only methods from the upper bound type will be available, but what about lower bound like this one?
thanks
 
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes. Remember that if you use <? extends Foo> you can take things out but not put things in.
Forget about casts. The compiler knows that everything which comes out of a Collection<? extends Foo> is a Foo, and that is enough to be getting on with.
Not sure about the upper bound question.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Spades wrote:my question is, when extracting the items out of listA, how does the compiler know what methods available for the extracted item?


Beyond those defined for Object, it doesn't; although I suspect (TBH, I've never tried it, so I don't know for sure) that the compiler might allow you to cast the returned object to a C (on the assumption that anything added using its own add() method must be a C or a subclass), but it'll almost certainly give you a warning about unsafe casts and, after the assignment of 'a', any such cast could well result in a ClassCastException at runtime.

HIH

Winston
 
David Spades
Ranch Hand
Posts: 348
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Yes. Remember that if you use <? extends Foo> you can take things out but not put things in.
Forget about casts. The compiler knows that everything which comes out of a Collection<? extends Foo> is a Foo, and that is enough to be getting on with.
Not sure about the upper bound question.



that's yes for which question? number 1?

@Winston:
I tried it and it didn't give any warning or compile error. It however, gave me a runtime error.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Spades wrote:I tried it and it didn't give any warning or compile error. It however, gave me a runtime error.


Sure it did, because you added an A, and you can't cast an A to a C.

I have to admit being quite surprised that it doesn't give you a warning though.

Winston
 
David Spades
Ranch Hand
Posts: 348
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yep,



simple casting is enough to access all methods available in class C and we know that the item was actually A. test() is just a blank public method I create in C only.
no warning, let alone compile error. but, I did get a big fat runtime error, as expected.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Spades wrote: . . . that's yes for which question? number 1? . . .

Yes. No 1.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Spades wrote:no warning, let alone compile error. but, I did get a big fat runtime error, as expected.


Fair enough. One thing that's worth remembering: Java generics isn't a universal solution, more like an 80% one; and the way it was implemented is actually a bit of a kludge (probably for backwards bytecode compatibility but, TBH, I'm not sure).

The fact is that you're unlikely to need a definition that includes wildcards in real life; they tend to occur far more often in parameters than on the LHS of assignments. And generics is good enough that if you run into problems, it's usually because you're over-complicating things.

HIH

Winston
 
David Spades
Ranch Hand
Posts: 348
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
let me summarize the discussion so far:
we shall refer the bracket content on the left hand side as "left expression" (because it may come in the form of expression ? extends A, etc) and the one on the right as "right type" (because it's always type on the right hand side)

1. It doesn't matter what type you choose for "right type" as long as when the wildcard on the "left expression" is substituted with "right type", the expression will pass, then it's all good
2. It has no effect whatsoever which "right type" you choose, there's not gonna be any effect at all. Is this true?

Thanks
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Spades wrote:1. It doesn't matter what type you choose for "right type" as long as when the wildcard on the "left expression" is substituted with "right type", the expression will pass, then it's all good


I think so, but I'd say that:
"if a generic type expression on the left hand of an assignment contains a "?", then any type supplied on the right (which CANNOT contain a "?") must satisfy it".
is a bit clearer.
However, it doesn't cover the case where the right hand side of the assignment is an object (and therefore may not have a visible type), as in your 'listA = a' assignment.

In that case, the object's declared type (if specific) must be compatible with the lhs, OR it must have been declared with the same wildcard expression.

2. It has no effect whatsoever which "right type" you choose, there's not gonna be any effect at all. Is this true?


Not quite sure what you mean here, because we've already stated that the type on the right MUST be compatible with the expression on the left.

Personally, I dislike the term "wildcard" for "?" expressions (although I'm not quite sure what I'd use instead), because it makes people think that the type is somehow 'variable'. It isn't. At some point in the process, you must have supplied a specific type, and THAT is the actual type of the object. The "?" simply says that the compiler doesn't know what it is.

HIH

Winston
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic