Many thanks for all the reactions on the first part of this blog post series, the Java Compiler. It’s great to see that Java can still generate so much passion and discussion, as you can see by the 140+ comments here:
…and more comments on RebelLabs too!
It’s fair to say at this point that I do have a couple decades of experience with several languages and environments. However, since time is finite, I don’t know half of them half as well as I should like; and I like less than half of them half as well as they deserve. So these posts are a snapshot of my own thoughts and experiences, not a quantifiable scientific report nor an in-depth comparison. Maybe some of my observations will sparkle a few useful thoughts and if you feel compelled to share your own, don’t forget that trolls are silenced by daylight if you just keep them busy long enough.
Let’s move on, there’s still a lot of ground to cover. As a reminder, here are my top 10 favorite things about the Java platform again:
- The Java Compiler
- The Core API
- The Java Memory Model
- High-Performance JVM
- Intelligent IDEs
- Profiling Tools
- Backwards Compatibility
- Maturity With Innovation
This time I’ll talk about 2. The Core API.
What rocks about The Core API
Interestingly, the most awesome aspects of the Core API are that it has always been there, that it still is there and that it’s still backwards compatible. It’s complete enough to allow you to write most applications without requiring anything else, should you wish to do so (the Java tools ecosystem doesn’t thank you ;-) . No, that doesn’t sounds very glorious, but I found that it has far-reaching implications that are enablers for other reasons why Java rocks.
That’s a wrap!
The most common complaint you hear about Java’s Core API is that it can be verbose, which is precisely why people use additional libraries like Google Guava or Apache Commons. Many even use another JVM language that provides concise language-level access to many of the Core API features (for instance: Groovy’s regular expressions, Scala’s string handling, …).
Most of these actually rely on the Java Core API underneath, wrapping around it and allowing library and language authors to focus on the neat features that they want to provide. Moreso, since the Core API is used underneath, it’s possible to mix and match your preferences without having to worry about being isolated in a niche where you have to convert or coordinate string implementations, threading primitives, sockets, … by yourself.
I was particularly surprised that it’s not uncommon to end up with three or more implementations of String in C++ projects, all different, all incompatible, all requiring you to perform the conversion yourself by going through byte arrays, handling the encodings, endianness, … This becomes even more troublesome for the threading primitives as Boost, Qt, STL, Juce, … again all have their own take on them. It’s already hard to get concurrency right, having to deal with subtle implementation differences, possibly even active at the same time, can be a real test of character.
Java’s decision to not only create a language and a virtual machine, but to also standardize the core libraries from day one, really paid off. Of course, other languages followed later with a similar approach, but few remained as stable as Java.
Stability allows you to move forward
Python is another language that has a nice core API with quite an extensive set of standard library features. Sadly though, it has been historically far from stable. Both the internal language type system and the standard libraries went through drastically incompatible changes over the years. This effectively ties existing projects to older versions, as it can be a major undertaking to port a large application to a newer version. The lack of static typing further complicates this since you have to make absolutely sure that all your code is either covered by automated tests or verified manually for each target operating system. It’s so daunting that entire books have been written about it.
Recently, I resuscitated my 10 year old RIFE framework and some projects built with it. It was a breath of fresh air when I found that I could just use Java 7 and move on. Everything already compiled, still worked and the few interface changes (specifically for JDBC 3 and 4) were spotted immediately by the compiler, allowing me to act upon them effortlessly. With Java 8’s default methods, even that will be thing of the past.
Stand on the shoulders of … everyone
When library and framework authors can communicate using the same programming language and the same API primitives, every project becomes another useful tool in the shed that incrementally increases the overall possibilities of the platform. This is certainly one of the reasons why Java has such a vibrant open-source community.
Developing in C++ was very frustrating when having to search for existing solutions since many of them relied on Boost, Qt or even other core APIs. Pulling those in would mean that an additional variant, which would need conversion and coordination, would be added to the project. This made selecting libraries very frustrating and troublesome, certainly if you take compatible licensing into account.
It gets better…
Summing up, Java’s core API is incredibly stable and backwards compatible, lets all sorts of libraries, frameworks and versions talk to each other and created the foundation upon which we build and use all sorts of other cool JVM stuff. This is why Java’s core API rocks.
Thus, being able to create a small project that can work together with any other project on your platform, even those from many years ago, is so powerful that it leads into rockin’ reason #3: Open-source … until next time (tempted by a Gossip Girl reference, but I’ll show some restraint).