- (For those already knowing everything about erasure, roll a 20 and go to number 2) Thanks to JDK 5.0 Generics, most people think that Collections can now be brilliantly assigned specific types of objects, removing the clutter of casting-all-around. Don't be afraid, but Generics in JDK 5.0 are not really the Generics you think they are! For reasons detailed below, Generics where sacrificed at the altar of Erasure! So let's be more specific. When you declare... say... a Map<String,BigInteger> myBigIntegerMap and a Map<String,Float>, the compiler will replace them with a Map and a Map! The compiler keeps all the code in a common class and adds some type conversions and type checks along with bridge methods for the specific types you declared, but it completely erases your beautiful type arguments from the runtime code. This is (insert dramatic drum roll here) type ERASURE (insert crash of cymbals here)!
The negative one is that you will never be able to discover these types by reflection, because nothing differs myBigIntegerMap.getClass() from myFloatMap.getClass()... and you'll have the surprise to see that (myBigIntegerMap instanceof Map) is a true statement! I can't wait to see the java puzzlers derived from these Generics...The positive effect is that it ensures backward/forward compatibility by (almost) not modifying existing collections and avoiding the mess that can be found in recent version of #ed languages and described in David dossot's blog entry. - The opposite system of Erasure is Reification. In this system, information is kept at runtime as first-class entities and can therefore be accessible for the true happiness of ORM tools developpers and such... Tough talks went on long before the release of Generics with JDK 5.0 about whether backward/forward compatibility could be attained with reification. It appears that such a goal could be attained, but is not even planned (as I know of) for JDK 6.0...
So knowing that two questions pop out of my humble mind:
Does a software of any kind always has to ensure backward and forward compatibility, even when slowing down innovations? Do JDK 5.0 code really has to run with older JRE's?
JDK should at least handle backward compatibility and moreover migration compatibility. Meaning that interoperability should be a real asset! This doesn't mean that Generics should be reduced to Erasure for the sake of it!
This just means that :
adapted Serializers could be coded in order to ensure compatibility with existing older codebase used through RPC calls could be codedadapters for older codebase used in the same VM.
I for myself saved my day by just asking myself the right question : what is the most elegant way of getting to my goal as I can not wait for JDK 8.0 ? ;).
My own solution was an annotation added to the Collection attribute I wanted to attain by reflection. Annotations can be attained at runtime by reflection, and are checked by the compiler. This adds a little bit of clutter and doubles the declaration of my type argument(s) but it does the job!
So I now have to declare :
@CollectionRuntimeInfo{type=Integer.class}
private List<Integer> myIntegerList;
private Map <String,Integer> myIntegerMap;
But I'm not (and will surely never be) part of the JCP, and am probably occulting a lot of potential issues... but it's still worth looking ;)
