Changes in Java 14 and 15

As we mentioned before Java started using 6 months release cycles instead of 2-3 years release cycles. This allowed developers to try out some proposed features and to give feedback. Here we will highlight changes in Java 14 released in March 2020 and 15 released in September 2020.

Java 14

Switch Expressions

First introduced in Java 12, switch expressions are the biggest changes in switches since including switching by Strings in Java 1.7. After two cycles of previews, now it is full part of JDK.
Example:

 

switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}

Now can be written like this:

switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}

Text Blocks

Text blocks are still being refined in preview mode. This time two escape sequences are added:

  • \: to indicate the end of the line, so that a new line character is not introduced
  • \s: to indicate a single space

Pattern Matching

Even after generics were introduced in Java 1.5, developers sometimes didn’t know what kind of objects they are working with. To handle this, JDK has an operator for testing against expected types.

if(object instanceof SomeClass){
    SomeClass someClassInstance = (SomeClass) object;
    someClassInstance.someMethod();
}

As we can see, the drawback is that after checking we have to typecast to the expected type. Now, explicit typecasting is removed by adding a variable name that will have typecasted value.

if(object instanceof SomeClass someClassInstance){
    someClassInstance.someMethod();
}

Records

Currently added in preview mode. Idea behind records is to remove boilerplate code in data objects. Let’s take an example data class:

public class Point {
  private final double x;
  private final double y;

  public Point(double x, double y) {
    this.x = x;
    this.y = y;
  }

  public double getX() {
    return x;
  }

  public double getY() {
    return y;
  }
}

It has final fields, getters and a constructor. Instead of writing this, we could use a record:

 

public record Point(double x, double y) { }

This will add constructor, getters, equals, hashCode and toString methods for us. Those methods can be overridden, but for any additional behaviour, a regular class should be used. This might seem similar to using Lombok’s annotations, but in this case we don’t have to use a third party library.

Helpful NullPointerExceptions

There isn’t a developer that didn’t experience NPE and trying to find it’s source. For example:

foo.bar.fiz.buz = 12

Will throw a NPE, but we wouldn’t know which object is actually null.

Exception in thread “main” java.lang.NullPointerException
at Prog.main(Prog.java:5)

Now, with enhanced NPEs log would look like this, and we would know exactly where the problem is:

Exception in thread “main” java.lang.NullPointerException:

Cannot read field “fiz” because “foo.bar” is null

at Prog.main(Prog.java:5)

Java 15

Sealed Classes

Java being an object oriented language and one of main features of OOP is inheritance. By default all classes are inheritable. One can control that by adding the final keyword, or making classes package-private. With sealed classes we can have a fine grained approach to inheritance. Example:

public sealed class Alpha permits Beta, Gamma, Delta { … }

Only Beta, Gamma and Delta can extend Alpha, and they must be in the same package or module.

Hidden Classes

Unlike sealed classes, hidden classes are a JVM rather than a language-level feature. The goal of hidden classes is to allow the runtime creation of non-discoverable classes. They cannot be linked by other classes, nor can they be discovered via reflection. They have a short life cycle, and thus, hidden classes are designed to be efficient with both loading and unloading.

Records

Still in preview mode, but with some changes:

  • Record fields are not modifiable through reflection
  • Native methods are prohibited
  • Similar to local classes, records can be local in scope
  • Records implement interfaces and work with sealed classes

Text Blocks

Text blocks are not in preview and now are part of Java SE.