Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.

Java 10 and beyond – a look at the potential language change

As mentioned in our recent webinar, the release cadence of Java has increased with Java 10. A new major version of Java is now released twice a year, in March and September. This means that we will already have Java 11 in five months’ time. This increased pace means that features can be delivered faster, when they are ready, so users no longer have to wait potentially multiple years. Just in the six months between Java 9 and Java 10, we saw numerous features added to Java. Expect to see a good number going into Java 11 as well.

But what exactly are these features that can now be delivered faster? In this post, I’ll highlight a few of the interesting language changes currently in development or proposed.

Local-Variable Type Inference

Java 10 introduced the language feature of Local-Variable Type Inference. This is the ability to use var as the type for local variables, and let the compiler figure out what type it is based on how it’s initialized. If you’ve used lambdas in Java, this shouldn’t be a foreign concept, as you can already do this as part of lambda parameter declaration:

Function<String, String> foo = (s) -> s.toLowerCase();

Here you’ll notice that you don’t have to specify that s is a String; it is automatically inferred by the compiler for you. Similarly now, with Java 10, you can do…

var list = new ArrayList<String>();

…and the compiler will infer that list is of type ArrayList<String>. Using var can help you reduce some of the verbosity, especially with regard to generics and cases where generics are already present in the initialization of the variable or implied in its name. Make sure that you don’t have to rely on your IDE to tell you what a specific type is; it should be easily available and understandable.

Java 11 enhances this further so var is also a legal type for lambda parameters, meaning the before-mentioned lambda can also be written as (var s) -> s.toLowerCase();. You might ask why, since leaving out the type does the same thing. A primary reason is that having a type present means you can annotate it as well.

For an in-depth guide to when to use var, and when not to use it, read Stuart Marks’ style guidelines.

Raw string literals

Another language enhancement currently proposed, and actively worked on, is the addition of raw string literals to the language. In a raw string, every character in the string is read as is, including newlines! This is especially useful for strings that would otherwise require a lot of escaping or span multiple lines. This could, for instance, be hard-coded HTML or an SQL query :

String html = "<html>\n" +
              "  <body>\n" +
              "    <p>Hello World.</p>\n" +
              "  </body>\n" +
              "</html>\n";

Using a raw string literal, it can be written like this instead:

String html = `<html>
                 <body>
                   <p>Hello World.</p>
                 </body>
               </html>
              `;

In the current proposal, backtick (`) is used as the raw string symbol. In cases where you need to use a backtick inside the string literal, you simply surround the string with double-backtick instead, or triple, or quadruple, etc., as long as you have the same number of starting and closing backticks.

String str = ```This is a raw `string` with ``backticks`` inside```;

While the JEP for raw string literals has yet to be targeted, a lot of the helper methods required for adding this are currently being added to String for Java 11, which could indicate that raw string literals might already be available in Java 11 as well!

Switch expressions

Multiple improvements to switch statements are also in the pipeline, including full-on pattern matching. But we are likely to see switch expressions before then. If you’ve ever written switch statements that simply set a variable based on what you’re switching over, then this is for you:

int val;
switch (str) {
  case "foo": val = 1; break;
  case "bar": val = 2; break;
  case "baz": val = 3; break;
  default: val = -1;
} 

With switch expressions, you can simplify that to:

int val = switch (str) {
  case "foo": break 1;
  case "bar": break 2;
  case "baz": break 3;
  default: break -1;
}

Meaning, break will also take the resulting value of the switch expressions, similar to how return works for method return values. In cases like the above, where break is the only statement for a case, a shorthand notation, similar to the lambda syntax, is proposed:

int val = switch (str) {
  case "foo" -> 1;
  case "bar" -> 2;
  case "baz" -> 3;
  default -> -1;
}

As said, adding switch expressions is a step towards pattern matching, which enable you to switch over more than just compile-time constants, but also include types, conditional checks, and much more.

There is already an implementation of switch expressions in the amber repository, so it’s just a matter of time until it will be finalized, fully tested, code reviewed, and approved, before it can be targeted and added to a JDK release. This could be as early as Java 11, as there are still two months until ramp-down phase one begins.

Other changes

Besides the above-mentioned language changes, there are many other things coming to Java in the near – and perhaps not-so-near – future. And more JEPs are being created with even more proposals, such as enhancements to enums to support per-enum generic type parameters, already-mentioned pattern matching, primitives as generics, intrinsics for controlling invoke dynamic, and, of course, value types.

Or how about launching a single-file class as a script, similar to how shell-, Perl-, or Python-scripts work on the command line? There are also many improvements on the way under the hood. These include changes to the JVM itself that don’t necessarily change anything on the language level, such as new ultra-low latency GCs (Shanandoah GC and Z GC), APIs for better interoperability with native code (Project Panama), changes to how inner classes work in the JVM level (Nest-Based access control), and many others.

So, when can we expect all of this? The answer to that is some March or September in the future. Some features do depend on each other, but with the new release cadence, the time from the feature being ready and us getting a JVM version supporting it has never been faster.

Whether this rapid evolving of the language and the platform is good for Java or not, I leave for the reader to decide.