Summary
I've just finished reading "Java Puzzlers: Traps, Pitfalls, and Corner Cases" by Joshua Bloch and Neal Gafter (Addison Wesley, 2005).
Advertisement
This is a collection of small, often simple examples that produce (usually) surprising results, along with an appendix of guidelines produced by examining the puzzles. Josh and Neal gave these examples at various Java One conferences, and it was one of the most popular talks there.
Although some of the puzzles fall into the category of "curiosities that you probably won't encounter," it's safe to say that virtually everyone will get some value out of this book. For one thing, Josh is one of the most careful people I know, and I will assume that Neal is also, by association. Neal was heavily involved in the generics implementation. So it's safe to say that the discussions are authoritative.
Both authors were part of the core Java development team at Sun, right up until the release of J2SE5, when both of them left for Google (a number of other core team members left at the same time -- has this phenomenon been analyzed by anyone as to how it relates to Java's future? Please post any links.)
One of the most interesting aspects of the book is what these two, who are about as close to the center of the Java universe as you can get, quietly said at the end of some of the puzzle solutions, in their "lessons for language designers." Which is to say, "if you are designing your own language, here's something you should do instead of what Java did." Which is to say "where Java didn't get it right," in the gentlest possible terms.
Successful Sun marketing efforts have created legions of folks who are happy to believe whatever the Sun marketing flaks say, and who descend like fire ants upon anyone who questions the design of any aspect of Java -- despite the fact that major flaws have been oh-so-carefully revealed by Sun itself. The biggest of these is threading, which has always been broken, up until J2SE5 (we'll have to see, but it seems likely that the issues have been revealed, and probably fixed), which we are all strongly encouraged to upgrade to. There are any number of other questionable design decisions, some large, some small. This is not to say that Java doesn't work reasonably well; what I argue with is when questions are stifled as they tend to be in this community. Not only do we not learn when this happens, but things go backwards because people believe that a design is good when it isn't, or that something is true when it isn't (Years ago, Gosling answered a performance question I asked during a press conference by saying that "Java has always been as fast, or faster, than C++," which naturally left me stumped, since I clearly didn't know by what measure he was making that statement).
Java has obviously moved the programming world forward, but I think its major wart has been the inability of the adherents to look at Java objectively. How else did we end up with EJB1 and EJB2, both of which were based on ivory-tower imaginations of design processes that no one has ever used? (Did anyone else but me get a strange feeling after learning about entity beans and then hearing that you shouldn't use them because they didn't work?) I only heard the full story at a session at the Colorado Software Summit last fall, which introduced EJB3 and explained how we got there. EJBs were the emperor's new clothes in duplicate, and yet the vast majority of people jumped on the bandwagon and created lots of big systems, "because this is the way we build J2EE systems," happily charging clients big bucks to build systems designed around an untried and fundamentally flawed concept, just because Sun marketing had pushed the idea. Who lost? The customers that paid for it. I know personally of systems that were built using EJBs, and then the customer had to pay for another consultant to come in and remove the EJBs to get the system to work right.
Attempts at discussion of the problems of erasure-based generics shows another example of a topic that was decided within Sun and handed to us as a fait accompli. Or consider checked exceptions, a feature that was invented for Java and which has not, to my knowledge, been duplicated in any language since. Despite this, I have not seen any suggestion that Sun considers checked exceptions anything less than the best idea in the world. The list goes on.
In "Effective Java," Josh pointed out a number of places where the language is flawed, and I think it's very valuable that Josh and Neal mention their "lessons for language designers." But it's too bad they don't go further, and begin to clear out the rose-colored fog we have been subjected to for so long by the marketing machine at Sun. The folks who have been breathing that fog do not notice "lessons for language designers" as what they are, a beginning of a critique of Java that might eventually make the language better. If we can't have an intelligent discourse about the flaws in the language, not only will the problems persist, but I think the amount of time that it takes a flawed design to come to light will slow the development of the language and libraries to the point that something else can pull ahead. For example, the EJB problems have taken many years to turn around, because there was no admission of how serious those problems were -- that might have cost vendors money in lost sales, so instead it was the customers who paid, and continue to pay.
Of course, the most important indicator of this trend may simply be that the two authors of this book, along with several other folks who used to be key members of the Java team, no longer work at Sun. Add to that the fact that, so far, J2SE6 looks like a point release (ironically, when we've finally started using whole-number releases) without much of anything exciting in it, and perhaps we can say that Java is now "stable." To be honest, I will be more than glad if that is the case. The 4th edition of Thinking in Java has been a huge project, and much of it seems to come from dealing with difficulties and obscurities rather than showing the power of great new features -- although, happily, there has been a significant share of that.
I watched C++ go from a nice little extension to an incomprehansible beast under the (mis)guidance of the ANSI committee.
Java is undergoing more or less the same trajectory. Each new release provides roughly the same power but with much more complexity. The language is an evolutionary dead end. I predicted Java would stop once it got templates because the introduction of the feature would introduce a lot of surprising behavior and take a long time for developers to adapt to it.
Prediction fulfilled. Java is now tremendously boring and pointlessly complicated. Next idea please.
Java does indeed seem to have reached its culmination. Of course it was inevitable eventually. One minor feature which, I think, made it happen sooner was the fact that depricated features were never dropped. Backwards compatability is a noble ambition but inevitably overwhelms the language eventually.
Interestingly, the 'good' guys can always be named but the 'bad' guys are invariably labled - conveniently anonymously - as either 'sales' or 'marketing'. In my experience, the lables are just polite euphanisms and the two groups are a lot closer together than we care to admit (publically). In much the same way that politians can always take the credit when good things happen and can always find someone else to blame when they don't.
Still, despite what various language advocates say, there doesn't seem to be any serious contenders to Java's crown yet.
> I watched C++ go from a nice little extension to an > incomprehansible beast under the (mis)guidance of the ANSI > committee. > > Java is undergoing more or less the same trajectory. Each > new release provides roughly the same power but with much > more complexity. The language is an evolutionary dead > end. I predicted Java would stop once it got templates > because the introduction of the feature would introduce a > lot of surprising behavior and take a long time for > developers to adapt to it. > > Prediction fulfilled. Java is now tremendously boring and > pointlessly complicated. Next idea please.
People forget that simplicity is power. Best to just create a simple core language that you can't imagine changing; one that is powerful enough to add every feature you can imagine via libraries, and then just stop. If you have to change the language to change the language, it seems like a failure of language design.
"Attempts at discussion of the problems of erasure-based generics shows another example of a topic that was decided within Sun and handed to us as a fait accompli."
While I didn't participate in the process, I really don't think that characterization is accurate. See the following link for some discussion about the discussions. http://gafter.blogspot.com/
"Or consider checked exceptions, a feature that was invented for Java and which has not, to my knowledge, been duplicated in any language since. Despite this, I have not seen any suggestion that Sun considers checked exceptions anything less than the best idea in the world."
Nor have you, I wager, seen any suggestion that Sun considers checked exceptions the best idea in the world. For the record, I think they are a good idea. The layout of the throwables hierarchy is another matter.
> People forget that simplicity is power. Best to just > create a simple core language that you can't imagine > changing; one that is powerful enough to add every feature > you can imagine via libraries, and then just stop. If you > have to change the language to change the language, it > seems like a failure of language design.
"Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary. Scheme demonstrates that a very small number of rules for forming expressions, with no restrictions on how they are composed, suffice to form a practical and efficient programming language that is flexible enough to support most of the major programming paradigms in use today."
Sadly, none of the mainstream languages are any good in this respect.
> People forget that simplicity is power. Best to just > create a simple core language that you can't imagine > changing; one that is powerful enough to add every feature > you can imagine via libraries, and then just stop. If you > have to change the language to change the language, it > seems like a failure of language design.
The problem with Java is the constant stream of new things added to the standard library... I agree that most if not all of what was introduced in Tiger we could do without, but the real damage wasn't the new language features. The real damage was done in 1.4 with the introduction of XML parsers, logging API, regular expression API, etc. etc. into the core libraries (all of those should have been optional addons like they used to be in the past). In Mustang it will get even worse, they're putting a complete SOAP implementation (including a fullblown HTTP server) into the core libraries.
The core language is still rather simple, it's the incredible glut of things which shouldn't be in the core library but are that is the main problem Java faces. And the crowd at java.net where many (mainly inexperienced it seems, and else people with a pet project) scream for everything and the kitchen sink to be included as a core library feature (or better yet a core language feature) are only going to make it worse.
I hope Sun never releases the language spec into the OS domain as then those people would go around and actually do everything they scream about Sun not putting in like multiple inheritance, surely destroying the language in the process even if the slashdotkiddos whose purpose it is to do so can't pull it off.
There's a massive case for proprietary right there, at least noone can change the language spec except the owner.
>I hope Sun never releases the language spec into the OS >domain as then those people would go around and actually do >everything they scream about Sun not putting in like multiple >inheritance, surely destroying the language in the process >even if the slashdotkiddos whose purpose it is to do so can't >pull it off.
Now that's contradictory. On one hand they're inexperienced crowd, on the other hand they are supposed to be skilled enough to introduce multiple inheritance to bytecode and JVM?
I, for one, am very pleased with all the stuff that was added to 1.4 (especially XML parsers, logging and regexps). This way i don't have to bundle 17.000 third-party jars with my applications and hope they play together well.