• Post Reply Bookmark Topic Watch Topic
  • New Topic

java generics super and ext  RSS feed

 
Jack Adams
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


Why does adding sorted map to a Set that allows ? super TreeMap and instantiated as such fail?
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jack Adams wrote:Why does adding sorted map to a Set that allows ? super TreeMap and instantiated as such fail?

Unfortunately, the best answer to questions like this is to look at the documentation. SortedMap's add behaviour because their keys are assumed to be in sorted sequence, but to detail it all here would take too long. The main thing that they offer is to return ranges of keys in the form of SortedMaps.

HIH

Winston
 
Jelle Klap
Bartender
Posts: 1952
7
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In this case you get a compile-time error because ? super simply doesn't work that way. It doesn't mean you can add any type that is a super type of TreeMap. It means that you can add any type of which TreeMap is a super type, including TreeMap itself. The difference with ? extends is that the latter would prevent you from adding to the Set, effectively (barring excplicit casts) making it read-only at compile time. The ? super construct does the opposite, you can only add to it, but not read from it, effectively making it write-only at compile-time.

Edit: If you Google the PECS (Producer Extends, Consumer Super) principle, you might find more detailed explanations.
 
Hauke Ingmar Schmidt
Rancher
Posts: 436
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Java checks the types at compile time. The way to check if the content of a variable can be put into a collection is by checking the type of the variable. This means: Java does not check at runtime what type the object has. That doesn't matter at all. The type of the variable is a guarantee that the object has at least that type, possibly more.

Your variable sm is of the type SortedMap. It is not of the type TreeMap. It doesn't matter at compile time that the variable can (and in this case: does) contain an object of type TreeMap.

It is more obvious when you don't have a local variable but a method parameter:



Now even you don't know if sm will fulfil the generic constraints of s.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hauke Ingmar Schmidt wrote:This means: Java does not check at runtime what type the object has.

Sure it does; otherwise, how would you get ClassCastException's?

Jelle's point (and I think most of ours) is that Java is a statically typed language, so the compiler can do an awful lot of this stuff for you. And it's just one of the reasons that I hate reflection.

Winston
 
Hauke Ingmar Schmidt
Rancher
Posts: 436
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
Hauke Ingmar Schmidt wrote:This means: Java does not check at runtime what type the object has.

Sure it does; otherwise, how would you get ClassCastException's?


I don't disagree; but it doesn't check in this context for selecting the method and checking if the object the variable is referencing is eligible for a collection.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hauke Ingmar Schmidt wrote:I don't disagree; but it doesn't check in this context for selecting the method and checking if the object the variable is referencing is eligible for a collection.

Well, the latter is down to generics, which is, perforce, a compiler-time check; but method selection, especially when it comes to which method to select when overriding (or overloading) is in place is also a runtime activity.

But perhaps we're arguing minutiae here. The fact is that Java is statically-typed, and the compiler can therefore do a great deal to ensure that you aren't doing anything stupid semantically; but it can't check for things that can only be determined at runtime - like the actual type of a real object.

Winston
 
Tyson Lindner
Ranch Hand
Posts: 211
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maybe the mistake that's being made, which is something I've admittedly done a ton while dealing with generics, is assuming that when you initialize your set or list or whatever, that the generic code somehow transforms based on the initialization.

For example if there's a class Apple that extends Fruit you might have:

ArrayList<? super Apple> list = new ArrayList<Fruit>();

Which works fine, but then you might incorrectly think the code is now equivalent to:

ArrayList<Fruit> list = new ArrayList<Fruit>();

But actually the "ArrayList<? super Apple>" part should still be read roughly as "an unknown list that can contain Apples". So we can't even add a Fruit to it, because the compiler thinks that the list could have easily been initialized with "new ArrayList<Apple>()" in which case adding a Fruit wouldn't work (the Fruit could be a banana). So really all the compiler feels its safe to add to the list are Apples, and since it checks reference types adding a "Fruit apple = new Apple()" object won't work unless we explicitly cast it to Apple.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!