Java 5 Sucks according to iBATIS Founder
I stumbled upon Clinton Begin's blog this evening and found his only post about how much he hates Java 5:
Anyone who knows me has already knows that I'm no fan of Java 5. Honestly, since Java 5 was released, Java has dropped from 1st to 4th on my list of languages that I consider when starting a new application. It was such a disappointment to me, both because of the poor implementation of the new features, as well as the omission of some fairly basic features.
...
I'm looking to Ruby, Groovy and C# 3.0 before I look to Java. Not so much because those languages are better than Java 5, but more because Java 1.4 was better than Java 5. Java is going downhill at the hands of Sun and the JCP. Sad, sad, sad...
Clinton has some very good points in his rant. Unfortunately, I don't think anything is being done to fix them.
For those that don't know, Clinton is the inventor of iBATIS and one of the heros of the Java Community that took on .NET when they said had a version of the J2EE Petstore that was one-third the lines of code (LOCs) and 28 times faster. Most of the JPetStore links don't work anymore, but you can read the announcement on TSS.
Clinton is also one of those down-to-earth type of people I really enjoy hanging out with. I've enjoyed several beers with him at many conferences and have always enjoyed his perspective. However, there's something that smells about this rant of his. If he hates Java 5 so much, and loves Java 1.4, why doesn't iBATIS implement a 1.4 feature? An enhancement request to support for JDBC 3 Generated Keys in iBATIS has been open for almost 3 years! C'mon Clinton - it would've taken you less time to implement this than to write your rant. ;-)
- Login or register to post comments
- 5573 reads
- Flag as offensive
- Email this Story
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)







Comments
Rick Hightower replied on Thu, 2008/02/21 - 3:29am
I had the "misfortune" of working with Java 5 and then going back to JDK 1.4 for 18 months to work with a great client.
All I can say was that it was painful going back to JDK 1.4.
Generics may not be perfect but I prefer type safe lists to random collection of gak. I much prefer List<Employee> getEmployees() to List getEmployees() especially when you find the that the method does not return exactly what you thought it did (employees example probably not the best).
I find all developers that I work with prefer Java 5+ and would not look forward to going back to JDK 1.4. In fact, I have never met a Java developer in person who prefers JDK 1.4 to Java 5.
I am for the evolution of Java. I don't want to go back to 1990s Java programming. Bring on closures, inferred typing, etc. "I say let... lets evolve, let the chips fall where they may."--FC 1999
Okay I read his post and... he makes some really good points about annotations. I don't agree with him about Generics per se (I thought it was a needed tradeoff for backwards compatibility), but I have never been happy with annotations. To each his own.
cowwoc replied on Thu, 2008/02/21 - 8:56am
Here is a simple proposal that makes old code run slower and new code usable with Reified Generics. I would love to see this implemented in Java7 in place of some of the other fishy RFEs which have been circulating.
Given:
When Java7 encounters this code it translates it into:
Where Collections.safeCast() is defined as:
Yes, this means that old code will run slower, but who cares? The point is that it will still run, period. If anything it will encourage people to migrate to Reified Generics to see a performance boost. New code will be more efficient and will benefit from runtime access to the Generic type.
This approach has the following benefits:
1) The compiler can stop accepting raw types (it'll throw an error instead of a warning), forcing all new code to migrate. Remember, developers have had three years to migrate their code already!
2) You can do away with most/all of the new warnings introduced in Java5. No need to litter your code with @SupressWarnings all over the place.
3) Runtime access to Generic types with all the new flexibility this implies.
Is there is a consensus on this issue?
Artur Karazniewicz replied on Thu, 2008/02/21 - 9:03am
I don't consider that Java SE 5.0 is worse than Java 1.4. But, the fact is, some features added to JSE 5 came with bag of snakes.
Just few examples:
Autoboxing - cool isn't it? Yep unless You know some dirty details like how does it work with overloading. It could be pretty magical. The bottom line is - autoboxing and widening works, but widening and then autoboxing doesn't work. Add to this varargs and You will end up with deep crap.
Generics - not much to add. Yust look at Generics FAQ by Angelika Langer - 400+ pages... C'mon its something substantial wrong with this...
Varargs - those are fine, once You understand that basically they are arrays (and for example You cannot overload method with array and varargs!).
This is not that JSE iw worse. Just it's much more complicated than JSE 1.4...
Clinton Begin replied on Thu, 2008/02/21 - 11:45am
Note to self: In the future, avoid abusing Blogger as a quick way to post a REALLY long response to a comment in someone else's blog...
Matt, RE: "[If Clinton] loves Java 1.4, why doesn't iBATIS implement a 1.4 feature"
Who says I don't like 1.3 better? j/k It's just time dude, just time. As you can see from my empty blog, I don't have a lot of it these days! :)
Clinton
Guillermo Schwarz replied on Thu, 2008/02/21 - 3:53pm
If you don't like generics, simply don't use it.
I don't like generics and therefore I don't use (much), but otherwise I prefer the enhanced for loop, it certianly makes code cleaner.
Also the new enum is a big improvement.
What I really miss in Java is closures. But please don't change the language. Make as easy as it is in Smalltalk, do not introduce cryptic syntax as for example:
{int x, int y => x+y}
Instead of this I would write:
int _(int x, int y) { retrurn x+y; }
A lot more Java like, isn't it? Notice the _ replacing the method name. Method of which class? An anonymous class of course.
And the purpose of this would be to have a method like this:
int f( int x, int k(int, int) ) {
return k( x, x );
}
Which receives a k method as argument and is called like this:
System.out.println( f( 2, int _(int x, int y) { retrurn x+y; } ) );
Or like this:
int k(int, int) = int _(int x, int y) { retrurn x+y; };
System.out.println( f( 2, k ) );
And then Java semantics shouldn't need to be changed.
cowwoc replied on Thu, 2008/02/21 - 4:08pm
in response to: gschwarz
Guillermo,
You misunderstand. I like the idea behind Generics and I *want* to use it. I just dislike the implementation of Generics in Java and I believe we would be better off cleaning that up because adding any more colorful features. Generics increased the language complexity and decreased readability in a big way. Like I said, I take issue with their design, not with the idea of Generics.
I would love for Sun to focus an entire release of Java purely on improving readability.
Jim Hazen replied on Fri, 2008/02/22 - 12:20am
in response to: cowwoc
Actually...this code breaks with a runtime exception because not all Animals are Dogs. Didn't you get the warning about the dangerous cast? :)
If this were a simple fix it would have been done already. Plus there are times when you're using third-party code that won't be updated and that you don't have the src for. Unless you're willing to throw away this code, you can't just stop supporting backwards compatibility.
Clinton Begin replied on Fri, 2008/02/22 - 1:47am
>> you can't just stop supporting backwards compatibility.
But you can imlement half a feature that creates more typing (in both senses of the word) with no additional type safety? ;-)
Here's my follow-up on backward compatibility:
http://www.clintonbegin.com/2008/02/backward-compatibilitybe-damned.html
Clinton
cowwoc replied on Fri, 2008/02/22 - 1:08am
cowwoc replied on Fri, 2008/02/22 - 1:18am
Okay, let's give this another go.
Here is the original non-Generic code:
Now, say someone compiled this in JDK 1.4 and then tried running it under JDK 1.5. In that case I believe the JRE should interpret the code as follows:
Essentially raw types go away in 1.5 and get interpreted as T = Object. Does anyone remember what backwards-compatibility problems this approach introduces?
Jim Hazen replied on Fri, 2008/02/22 - 4:07am
in response to: cowwoc
As far as I know this is essentially what happens. The problem wasn't with 1.4 classes being compatible with 1.5 it was with 1.5 classes working on Java hardware devices. The hardware couldn't be made to understand new parameterized types and with so many devices out there it was deemed unacceptable for 1.5 classes not to run on them.
Eventually I do think there will come a day where some backwards compatibility will be scrapped. That hardware evolves and is recycled so frequently that the benefits of moving forward will outweigh staying compatible. Should it have come with Java 5, who knows.
I do know that I much prefer Generics in their current incarnation than not having them at all.
Dimitris Andreou replied on Fri, 2008/02/22 - 9:23am
>The problem wasn't with 1.4 classes being compatible with 1.5 it was with 1.5 classes working on Java hardware devices
The problem was migration compatibility, read it up here:
http://gafter.blogspot.com/2004/09/puzzling-through-erasure-answer.html
cowwoc replied on Fri, 2008/02/22 - 12:26pm
in response to: Dimitris Andreou
I read Neal's explanation and if I understand him correctly the crux of the problem is:
So my question then is, now that Generics has been out for five years (3 years since JDK 1.5, 2 years in prototype phase), isn't it possible to degrade the performance (keeping compatibility!) of older code in exchange for Reified Generics? Couldn't you fix the above problem as follows?
What do you think?
Guillermo Schwarz replied on Fri, 2008/02/22 - 8:46pm
cowwoc,
I agree with you completely. Java generics complicate the language. The same happened with templates in C++ and C++ took at least 10 times more to learn than Java, which meant that templates made C++ unusable.
Java today is still usable, you just need to stay away from the heavy use of Generics that STL was in C++.
In order for Java to have closures, the return problem must be solved.
For example in Smalltalk you can type:
a := true.
[ a ] whileTrue: [
x := x + 1.
(x > 10) ifTrue: [ a := false ].
].
(x > 5) ifTrue: [ ^x ].
The same in Java would be:
int f() {
a = true;
while ( a ) {
x = x + 1;
if (x > 10) { a = false; }
}
if (x > 5) { return x; }
}
Passing the blocks as parameters:
int f() {
a = true;
Block block1 = {
x = x + 1;
if (x > 10) { a = false; }
};
while ( a ) block1.run();
Block block2 = { return x; };
if (x > 5) block2.run();
}
How does Java know where the return returns from?
One idea is to have a variable pointing to the current context, so that intead of writing:
return x;
We would write:
currentContext.return( x );
Dimitris Andreou replied on Sat, 2008/02/23 - 12:20am
in response to: cowwoc
Reified generics is an option that Gafter also discusses in his blog:
http://gafter.blogspot.com/2006/11/reified-generics-for-java.html
It sounds doable, although it involves the creation of parallel APIs (like C# introduced a second set of collections to accommodate reified generics).
I don't think the ultimate solution could be as simple as a cast between List<Object> to List<T>, for some T, though (it would have been done already). But then, I also haven't spend as much time as Neal pondering on the relevant issues. Probably he has a straight-forward only-line answer, so why don't you forward your question to him?
cowwoc replied on Sun, 2008/02/24 - 1:25pm
Neal brought up good points:
- An object cannot be simultaenously a List<Object> and List<String>. Collections.checkedList() simply wraps the underlying list and executes checks at runtime.
1) Once you wrap the List<Object> in a List<String>, what's to prevent someone from adding a non-String to the underlying List<Object> while the List<String> is being used? You could have a special List<Object> implementation which throws an exception at insertion time if this happens but old code will now throw an exception at a different place than it used to (at insertion time versus at retreival time). This might or might not be a big deal but it's worth considering.
2) By wrapping behind the scenes, you're changing the identity of the object sent by the caller and received by the method. If they attempt to synchronize with each other on the object, for example, they'll be synchronizing on different things.
Ideas are most welcome :)
cowwoc replied on Sun, 2008/02/24 - 4:40pm
You can say many things about Neal Gafter, but it seems that "diplomatic" is not one of them. Today he posted a not too tactful reply to my request for feedback which I found both offensive and bordering on arrogance: http://gafter.blogspot.com/2006/11/reified-generics-for-java.html#c8374851026588442066
I fully appreciate the fact that Neal has more experience than most people in language evolution and that he might not have much time on his hands but I really don't feel this justifies the tone of his reply.
I now understand what Charles Nutter means when he talks about the Java "Ivory Tower": http://www.infoq.com/interviews/qcon-panel-java-future
In my view, there is absolutely nothing wrong with individuals bouncing ideas off one another without delving into the level of formalism discussed here: http://blogs.sun.com/darcy/entry/so_you_want_to_change
The latter document makes it pretty much impossible for any one person to make a difference in the future of Java because of the huge amount of overhead imposed on any proposal put forward. I appreciate the fact that we *need* this level of formalism before a feature ends up in the language but I don't think it is appropriate for the brainstorming phase (which is where we are now). The people who initially come up with proposals are not necessarily the same people who will drive it through JCP and produce all the required formalisms. JCP represents a tiny minority of the Java population. Implying that anyone who doesn't "go the mile" through JCP doesn't have the right to discuss language changes pretty much guarantees that you end up with a designed-by-a-commitee API as opposed to what the community at large is looking for.
There are already existing JSRs whose goal is to improve Generics. I just wanted to see if I could contribute to their efforts in a small part. In my view, we should be encouraging this kind of debate, not trying to stifle it. Just my 2 cents.
Dimitris Andreou replied on Mon, 2008/02/25 - 1:48am
in response to: cowwoc
cowwoc replied on Mon, 2008/02/25 - 2:12am
I trust Neal's expertise on the topic, I just didn't appreciate the tone of his reply. He could have been a lot more polite. That said, it would also be useful for someone (it doesn't necessarily have to be Neal) to post a comprehensive FAQ on the design decisions behind Generics and simply point people to it whenever such questions come up.
As I mentioned in my initial posts, I suspected that my proposal overlooked something obvious but I couldn't see it myself. I was simply curious what I was missing and what requirements were behind some of the design decisions of Generics by erasure.
I appreciate all the help you and others in the community have provided to this end. Thank you.