Generics - good or bad?

(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? :frowning: 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 :stuck_out_tongue: - 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 :(.

NB: I’m not 100% sure about the interactions of wildcarded generics with other generics, so my misunderstanding of that aspect may invalidate some of the complaints above. So far, AFAICS, wildcarded generics don’t really solve any of the above problems, they just shift the difficulties elsewhere (but still in programmer source code, rather than dealt with by the JVM)

I have no idea. I was at a C# lecture at m y university by one of the key designers of c# 2.0. They have implemented generics as well and avoided all those issues, and gained more speed.

But the fact that generics get translated into Object at compile time pisses me too… It has something todo with SUN not wanting to change the virtual machine.

Anyway in C#, this is not the case

Uh, theres no removed features so I can continue to program in exactly the same way as with 1.4. How does this make things harder to use?

Bruce Eckels has a much shorter commentary, dwelling on far fewer of the problems, here:

http://mindview.net/WebLog/log-0050

that concludes:

[quote]The conclusion that the Silicon Valley Patterns Group came to was that these so-called Generics seem to only solve the problem of automatically casting in and out of containers.
[/quote]
…which is accurate, and the item has some good points, but skirts around many of the issues (and is wrong on one point IMHO). If I get time, I’ll write up a more detailed analysis, based on any feedback to this thread here :).

Ah, yes. What I really meant was:

“This new feature will be used widely; even if it weren’t, it’s a syntax change, which means that in order to continue being regarded as a serious java developer you will NEED to understand it. In many cases, you will be forced to use it, as libraries and API’s convert to it”.

Already Sun has started converting their standard libs to generics. Sure, you can (at the moment) ignore this, but some of the ways in which you can ignore it are forwarned as possibly going to be made illegal in future (e.g. “raw” generic types).

It is generally hard to avoid keeping your data homogeneous - i.e. when your API uses generic types, you usually have to jump through hoops not to use the same types internally - which further increases the pressure to adopt them.

I have no doubt that generics will become all pervasive; I just doubt whether they are - on balance - a net benefit to the language (and I find it EXTREMELY worrying that I’m even considering this - that something we have to live with and is as major as a syntax change might yet be damaging to the language? Just that doubt is enough to suggest java long-term is in trouble, or at least dangerous waters).

LOL. This is the kind of thing I thought would never happen whilst java remained non-open-source. Perhaps Sun’s claims for java to be “almost if not quite open-source” are more accurate than I’d given credit for? ;D

I’ve been thoroughly unimpressed with Java’s take on generics since they were first mentioned. I also remember a lot of the problems that their equivalents (templates) caused over in the C++ world for years, particularly when combined with the bloated, horrible STL. I’ve had to do some maintenance work on some C++ code that uses templates and the ability for the developer to royally screw everything up with very minimal effort is unsurpassed!

For what we need in our projects, I highly doubt we’ll ever make use of any of the new “language features” in J2SE 5 unless some of our lower-level library usages force us down that path. Anywhere that generics may have been useful, which is in the java.util packages, we’ve already got a set of better libraries written that do it faster and with less or no garbage generation. We’d only see a net loss in performance and reliability by going to use generics for these uses.

Bollocks to generics.

Cas :slight_smile:

For my code, which is based on 1.5 anyway - because I wanted the nanosecond builtin timer - I’ve starting using the generics feature.

I like it. A Map <String, MyType> is a more meaningful return type than Map, for example.

I did find it odd that you can’t have arrays of generic types - that’s annoying.

Yes, this is one of only two places I’ve so far found where generics seem to do much genuinely useful (i.e. fixing collections).

Although it seems that they’re so crap they can’t even accept basic datatypes, even though other java generics compilers do!

The other use I’ve seen is very esoteric - far more esoteric than, for instance, the benefits of operator overloading. Certainly, it seems right now that allowing the generics proposal was an incredibly bad thing from JCP / Sun (allowing an “operator overloading” proposal being one of the few that would IMHO have been considerably worse ;)).

But I keep hoping I just don’t get it. That perhaps Sun has some secret plan for fixing generics in the future. If all they are is a quick hack to make collections slightly less crummy then Abandon All Hope Ye Who Enter Here! We’ve moved from a carefully thought-out language with huge care taken to avoid things like pointer arithmetic, to spectacularly ugly and unhelpful and confusing hacks like this one whose sole purpose seems to be to eliminate something they embarassingly got wrong and never thought of a good way to fix.

AFAICS, generics is far more embarassing, and I fear going to cause far greater losses in productivity, than that which it supposedly fixes :(.

If this is the shape of the future, then I can see a Java fork appearing just as soon as the GPL people have a version that isn’t so utterly incomplete as to be unusable - simply because the millions of java programmers can’t afford to be screwed over with crap like this >:(.

" Although it seems that they’re so crap they can’t even accept basic datatypes, even though other java generics compilers do! "

You mean primitives? I guess that’s why they included the autoboxing feature I guess, but IMO autoboxing is a crap idea. I’ve done a bit of C# programming and I ended up hating autoboxing because it loosens typing. (It’s legal to assign object to int and v.v., but is this object containing a boxed int, or not? Not an issue when you type something with generics - which is why I like it,

I really like Generics, but then I only use them for avoiding casts in the Collections framework. I’m not writing any code in which I’d need to implement a generic myself, so I can’t comment on that side of things - but to a user of the technology, they’re fantastic!

[quote]I really like Generics, but then I only use them for avoiding casts in the Collections framework. I’m not writing any code in which I’d need to implement a generic myself, so I can’t comment on that side of things - but to a user of the technology, they’re fantastic!
[/quote]
I wrote a response to this, that kind of said “sure. But the reason I’m annoyed is…” and decided it was too much of a personal rant :wink: so I’ll leave it until / if I write this up more coherently as an opinion piece.

[quote]" Although it seems that they’re so crap they can’t even accept basic datatypes, even though other java generics compilers do! "

You mean primitives?
[/quote]
Yup. FYI “basic datatype” was the terminology we were taught at Uni, and it stuck. That could well be just some 20-year old term that came from Modula-3 which the professors were using because they were still bitter that Java had supplanted it ;), but I thought this was the standard term from JLS 1 days. :slight_smile:

I’m just deeply unhappy that it a) can’t take primitives b) can’t be used with arrays and c) erases the type information under the hood, making whole classes of optimization impossible :frowning:

Cas :slight_smile:

If you don’t like generics you only have to write the constructors without the template extra syntax i think.

Like this:

List list = new ArrayList();

its perfectly legitimate syntax and you only get a warning that you are using unchecked code.

[quote]If you don’t like generics you only have to write the constructors without the template extra syntax i think.
[/quote]

  1. Sun have stated that they are considering making that (“raw types”) illegal syntax in the long-term (perhaps java 6?)

  2. Since Sun have screwed up and made generics types incompatible with arrays, statics, and interfaces, and have “upgraded” their own libs to use generics, it is certainly not a case of being an “optional” item. Unless you refuse to upgrade to java 1.5. And just pray none of your 3rd party libs upgrade and force you to…

[quote]I like it. A Map <String, MyType> is a more meaningful return type than Map, for example.
[/quote]
Of course.
It’s meaningful: Map <String, Yourtype> yourvar.
Compared to this, which means nothing: Map yourvar.

Furthermore and more importantly it finally brings compile time safety in most cases. Doing a
Yourtype anothervar = (Yourtype) yourvar.get(“bla”)
is just sick. This works for mickey-mouse mini programs but not for large apps. It’s as sick as using non-compiled BASIC and seeing runtime errors when the last bit of your code is being executed - and no earlier. (I used to use BASIC a lot so yes it’s been cool in ancient times but not anymore.)

Type safety is the most important thing on generics I think. I don’t know if SUN “screwed up” generics in Java 1.5 but I don’t think so. I used them for years in C++ and I finally get them for Java, so presto. I’m pretty sure most of us here aren’t in a position to judge if SUN did a bad job, because there’s no compiler experts here around. On the other side I really can’t imagine that tea boys would have invented the new Java 1.5 language extensions, so… let’s be optimistic.

I know an awful lot about compilers :frowning: The reason generics are implemented the way they are is because, in a nutshell, it was too expensive and difficult to change the VM to cope and still keep it backwards compatible. We couldn’t have our cake and eat it so…

Cas :slight_smile:

Generics is a good addition. It could have been done better with JVM changes, but the current implementation is acceptable. The only thing that bothers me is that you can’t (easily) create arrays for a generic type.

It’s a good feature that calling static methods on a type parameter is disallowed. The parameterized type must be compilable without knowing the exact type of the type parameters.

List shouldn’t be a subtype of List because then the compiler would allow you to add any object to a List. This is where wildcards are useful. They are extremely powerful when used correctly. Java array typing is broken so that methods like System.arraycopy() can work.

The primitive type limitation can be worked around by creating special collection classes for primitive types. Too bad Sun hasn’t included such classes in JDK 1.5. They could have at least added classes like intVector, floatVector etc. But maybe they think we should use autoboxing instead, which is one of the worst features of Java 1.5. It is very seldom useful, will create many strange bugs and the performance and memory usage sucks compared to using special collection classes for primitive types.