Java Then and Java Now

9pm on Monday 24th June, 2019

Influenced by the breakneck speed that other programming languages, libraries and softwares are iterating, Java has adopted a new faster release cadence with a new version scheming to go with it.

Prior to this, Java typically released around every 3 years. These usually involved many big changes to the language and its standard library from a single major version upgrade. In the new world of twice-yearly releases, we can expect features to be released shortly after they're completed, instead of waiting for the laundry list of features slated for a particular release.

Java 9 - The New Module Path

The biggest change that's been released so far is the new module system introduced with Java 9. The introduction of the module system in Java, sometimes referred to as Project Jigsaw, allows for more fine-grained control over what is and isn't accessible within a Java library or application.

As packages are to classes, modules are to packages, allowing you to define boundaries between packages in your applications. This encapsulation is enforced by the JVM and at compile time, so it's now necessary to define which external modules you require, and which packages you export, if any. This compile-time check means that required dependencies can be checked at compile time, as opposed to the classpath where dependencies weren't checked until the required class was actually used.

Thankfully it's relatively easy to incorporate the changes that the module path require, and it's not required to fully "buy-in" to the module system just yet. Since there will always be legacy libraries, and in the interim of the popular libraries updating, JAR files which do not contain a top-level module declaration file define what is called "Automatic Modules". In an automatic module, every package is exported and every other module is required by that module. This allows older libraries to work even when using the module path.

There are a lot of good tutorials for checking out the new module system, so I won't get into technical details here, I would recommend this one.

New Java Feature Highlights

Since Java 9 came out, a few new immediately-useful features have come in the following versions (we're on JDK12 at time of writing). Other features will be covered in later posts, as well as the side effects of other changes.

The var keyword

A few of these changes can be described as syntax only changes, some of which make improvements to unnecessary verbosity, and others which are paving the way for new language features. We'll start with the most inert of them.

The var keyword is a simple but effective change, whereby if it is obvious what type something should be then the type can be replaced with the var keyword. For example:

var hello = "hello world";
hello instanceof String // true

This does mean generic types which are normally instantiated with, for example List<>, can be done also. The following two lines are equal (up to type casting).

var myList = new ArrayList<String>();
List<String> myOtherList = new ArrayList<>();

This is purely a superficial change though, the types still work exactly as before, so you won't be able to re-assign a variable to a different type.

var x = 5;
x = "world"; // compile time error

With Java 11, you can use the var keyword with your implicit lambda types, so you can now add annotations/modifiers to these values without losing the brevity of lambdas.

(@NonNull var x, @Nullable var y) -> x.compareTo(y)

Switch Expressions (Preview)

On the path to full pattern matching, switch statements have gotten an upgrade in the form of switch expressions. They're currently in preview in Java 12 and 13, so the --enable-preview flag is needed when compiling and running. Hopefully they'll be available fully soon. In the meantime let's take a look at a new switch expression.

boolean result = switch (myInteger) {
  case 1 -> true;
  case 0,-1 -> false;
  default -> throw new IllegalArgumentException();

The first thing you'll notice is the new syntax, which is cleaner for short cases. It's still possible to use the old case x: syntax. This is also true with the multiple cases as seen above. Previously this meant multiple case statements, but now a simple comma separated list of values can be used.

Lastly is that since this is a switch expression it can outright return a value as seen above. It's worth noting that, like pattern matching in other languages, you will need to exhaustively define this value for all possible cases. This often means adding a default case, but if an exhaustive list is possible such as with enums, then covering all possible enum cases is sufficient.

Text blocks (Preview)

Coming in Java 13, albeit under the preview flag, is text blocks - a feature many language already have - that allows multi-line strings. They don't currently support any type of interpolation, but may in the future. Hurrah for readability!

String insertQuery = """
  SELECT username, email, address, phone_number
    FROM users
    WHERE phone_number IS NOT NULL
    ORDER BY username ASC;

HTTP Client

The new HttpClient in Java 11 is a HTTP Client for the today's web. It's a sorely needed replacement for the HttpURLConnection API that's existed since Java 1.1. Those that are familiar with Apache HttpClient will feel right at home if they start using this API.

Within it is support for HTTP2, websockets, making requests synchronously or asynchronously, as well as being able to use reactive streams for response data. The Javadoc can be found here.

Wrap Up

The biggest change here is the module path change and it's important enough to call out again here. The real benefits of it will begin to shine once it's more embedded in the more popular open source libraries. However, familiarising yourself with it now will make your future easier for when that new project comes around, or make your life less painful when it comes time to upgrade. Luckily that's not any time soon though, with Oracle providing support for Java 8 until 2025.

Permalink Java, Programming