In the last day of Devoxx, one of the most anticipated sessions was Joshua Bloch‘s The Evolution of Java: Past, Present, and Future. As Joshua put it, the intention of his talk was to critique every single language feature which appeared in the language since its first version. In many ways, this talk was a continuation of Joshua’s talk Java: The Good, the Bad, and the Ugly Parts from the first conference day, already covered in one of Ivan’s previous posts. The session went through all features introduced in Java from 1.1 to 7, explained their intention, showed their “good, bad, and ugly” parts, and finally presented a rating on a scale between “Success” (happy Duke) and “Failure” (Duke shooting himself in the leg).
In the beginning of the talk, the speaker revisited one James Gosling talk from 1996 and a subsequent article The Feel of Java which was published few months later. According to Gosling, Java is practical, not theoretical; it does not introduce new ideas but prefers tried-and-tested things; it feels hyped, playful, flexible, deterministic, and non-threatening. All these characteristics were the main reasons for Java’s worldwide success. There were also naysayers – for example, Bjarne Stroustroup predicted back then that Java will inevitably become more complex and develop implementation specifics. So the ratings of the language features were based on Joshua’s judgment of the extent to which each of them managed to preserve the original “feel of Java”. Features rated as success are simple, useful, and widely adopted, while those rated as failure are either too complex, obscure, or have serious design flaws which lead to “puzzlers”.
Java 1.1
- Nested Classes. Provide better encapsulation and rudimentary closures. The fact that they are non-static by default is often wasteful and can be deadly; mixing inheritance and non-static nesting is evil. So they are not good enough for closures, should have been static by default, and are still not supported by the VM. Conclusion: not a bad feature, but could have been really good. Neutral
- Serialization. Besides library, this is also a language feature, since it impacts the design of arrays. One major weakness is that it doesn’t get along with instance control, e.g. singletons. It sort of works, but has a lot of flaws: introduces a hidden constructor; has security holes; leaks private fields; performs abysmally; introduced bugs (Hashtable); designing readObject methods is really hard; final fields don’t mix; requires casting; the serialVersionUID is needless clutter. Conclusion: arguably the worst feature ever added. Failure
Java 1.2
- strictfp modifier. Addresses an idiosyncrasy in Intel’s x87 math coprocessor. Conclusion: minor wart that could have been avoided. Failure
Java 1.4
- Assertions. Back in 2001, Joshua encouraged developers to “accept assertions into their lives”. There were and still are good reasons for this, but sadly his advice was mostly ignored – maybe he didn’t preach enough, or maybe developers felt uncomfortable with the uncertainty whether assertions should be switched on or off in production. As a result, most programmers get little benefit from this feature. Conclusion: a net win, but barely. Neutral
Java 5
- Generics. Enforces specification at runtime, achieving “stronger typing with less typing” as Joshua put it back then. However, adding wildcards at the last minute was a disaster, and generics finally turned out so complex that even the best programmers don’t understand the intricacies. Conclusion: generics are essential, but the design was wrong, “we blew our complexity budget with this feature”. Failure
- Annotations. General purpose metadata facility. Although it wasn’t perfect, it was well integrated and enabled many successful projects. Conclusion: success – modestly useful for many, critical for some. Success
- Enums. Combines the power of the typesafe enum pattern with the ease of use of regular enums. Conclusion: rip roaring success. Success
- Enhanced for loop (for-each). Lets you iterate over collections. Conclusion: most successful language change to date. Success
- Autoboxing / Unboxing. As Joshua put it, “dragons lurk in these waters” due to many design flaws. This feature achieved reduced verbosity, but the distinction between primitives and objects still exists, and more puzzlers were introduced. Conclusion: instead, generics should have been made to work for primitives. Failure
- Varargs. Variable number of parameters in method declarations, mainly for printf and reflection. It turned out to be very useful, but not very often. Conclusion: a flawed success, made worse by generic shortcomings. Neutral
- Static Import. Conclusion: very modest success. Neutral
Java 7
- Strings in Switch. Useful, but may encourage overuse of String. Conclusion: modest success. Success
- Binary Literals, Underscores in Numeric Literals. You can express the US national debt as “14_516_500_000_000L”. Conclusion: modest success. Success
- Multi-catch. Conclusion: no known downside, moderately big win. Success
- More Precise Rethrow. Conclusion: modest win. Success
- Type Inference for Generic Instance Creation ( operator). Reduces the verbosity of generics. It is complex under the surface, but this complexity is not exposed to developers. Conclusion: big win. Success
- Try-with-resources. Introduces linguistic support for the “dispose” pattern. Eliminates lots of verbiage, without significantly complicating the language. Conclusion: big win. Success
- Safe Varargs. Conclusion: modest success. Success
Where are the puzzlers in Java 7? Maybe there aren’t going to be puzzlers – but don’t bet on it.
Future
Regarding Java 8 and beyond, Joshua advised the language designers “not to give Stroustroup the last laugh”. More is not always better, so before adding a feature a genuine need should be demonstrated.
Conclusion
This talk was informative and entertaining, and offered a very interesting perspective to the history of Java. I liked the speaker’s attitude, really objective and honest even when evaluating features for the design of which he has responsible himself. In Java and other JVM-based languages, are today’s hypes tomorrow’s puzzlers? Or have the language designers really learned from their past mistakes?
I believe Bjarne Stroustroup’s prediction has largely already become true. “The feel of Java” was attractive and compelling, so Java became a great success. However, during its further evolution the language designers had to add many additional features to maintain its viability. For some developers even this was not enough, so they switched to new JVM languages such as Groovy and Scala which favor conciseness, consistency, and expressive power over simplicity. “Polyglot programming” instead of “The feel of Java” is today’s norm – let’s see for how long.
If you discover youself to be along the side of the majority, it is time to pause and reflect.
Nearly all quality improvement comes via simplification of design, manufacturing… layout, processes, and operations.