(nb: this is based on detailed reading of the unofficial generics FAQ linked here: http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=cluebies;action=display;num=1097304934 because I wanted something easier to understand and which exposed more of the side-effects than the docs I’d previously read. There may be mistakes in that doc which I’m passing on. And I could well have misunderstood some stuff, so…)
I hadn’t realised until now just how much JCP/Sun screwed up generics by insisting they were a compiler-only syntactic sugar. Recall we had the debate about how they OUGHT to be more than sugar - how they ought to be understood by the runtime, reducing usage of casts, and reducing amount of type checks etc.
Well, I’ve only just realised how many other things, at the language-level, are screwed up by this too. AFAICS, generics is going to go down in history as one of those things that made java considerably harder to use in the long-run, since it is excessively and needlessly inconsistent with the rest of the language. (NB: that FAQ excuses most of this with “…hence X doesn’t make sense” which either means the author is a bit dumb, or being very kind to the generics designers, or failed to think about the alternatives. It’s certainly not true in all cases bar the one about Enum’s, and even there it isn’t a trivial argument)
Problems introduced by the way they chose to implement generics:
[] Generics can’t interact with “static” stuff. At all. Ever. Including…interfaces! (there are hacks you have to use to get around this when you want to pass information between a parameterized class and an embedded interface. This is frickin’ ridiculous, and makes bizarre-looking code)
[] Generic types are all identical at runtime - hence they CANNOT be type-checked at runtime. No “instanceof” calls for you, my friend!
[] …and that breaks several other things in java’s type system. For instance, generics cannot be covariant (i.e. List is NOT a subtype of List despite the fact that most people would assume it ought to be…), partly because the runtime has no way of understanding this concept and checking it. How many bugs and headaches and how much pain are developers going to have because of this particular “feature” over the next 5 years?
My guess is rather a lot - especially for anyone fairly new to java who also is having to learn the rest of the language at once, and getting their mind blown to pieces with the inconsistency of it all. Arrays are co-variant. Generics are not. Methods may or may not be, accordng to context and/or the use of the explicit covariant stuff (?).
[]…and because arrays are covariant but generics are NOT, you are NOT ALLOWED to put generics in arrays unless the generics are unbound (i.e. nothing or <?> as opposed to being ). It makes sense from the implementation perspective, but it’s UTTERLY SCREWED from the language-design perspective.
[*] …and generics that are unbound/raw and placed into an array BREAK ARRAYS, allowing any incompatible type of the generic (remember, these things cannot be instanceof checked) into the array, which breaks the fundamental design/contract of arrays. (Hmm. Now I know why Sun isn’t keen on design-by-contract - it prevents you from making evil language changes like this one
- sorry, couldn’t resist ;))
So, in conclusion, any newcomers to java now NEED to understand the JVM/runtime as well as the language in order to use the language. Sure, this has always been the case to a limited extent, but Sun/JCP’s decisions are pushing it further in that direction. IMNSHO this is an incredibly bad and stupid decision - they are making java into a language where you have to understand it’s pseudo architecture more and more just to use the language at all simply to reduce implementation effort.
Whilst I’m all in favour of backwards compatibility, and the concept that any JVM can run any java code, independent of version, they have already made 1.5/5 code IMPOSSIBLE to run on older JVM’s (refusing to invest the effort to produce something like Toby’s excellent Retroweaver - if you don’t know about RW, you can’t run 1.5 code on earlier VM’s), so WHY bend over backwards with generics to make it compiler-only? ???
I’m completely stumped on this one :(.

so I’ll leave it until / if I write this up more coherently as an opinion piece.