As of the release of Java 17 a new LTS has been available, but what is in it for me exactly and which features can I use during projects?
Most of the blogs I read only describe 1 version upgrade and also discuss a lot of features that are/were still in preview.
I decided to summarize which features are released from java 11 to 17 (one LTS to another) and in specific only those that I thought could be interesting during my everyday work as a Java developer.
So in this blog I wont be talking about the features that are in Preview or tools that came with the new JDK’s.

Helpful NullpointerExceptions

You love to hate them, NullpointerExceptions…​ But they got a little better because from now on the exception will tell which variable is the culprit. And I know, the best NullpointerException is no NullpointerException at all, but still once they occur they better tell what’s wrong.

java.lang.NullPointerException: Cannot invoke "String.isBlank()" because "myStringVariable" is null

This feature has been released since Java 14, in Java 15 they made the extra information about which file/line had caused the error as default.

Text Blocks

Text blocks are new to Java and will enable you to create readable multiline strings. To create a Text Block you can create a String variable but instead of typing text between double-quotes " you type them between 3 double-quotes """ and start your text on a new line.

For example:

String s = """
Hello world!
My multiline string is here!

One of the advantages of using text blocks is that you can create formatted strings that are readable, which will improve code quality.
At runtime the jvm will look at the textblocks and will ignore the minimal amount of whitespaces before the first non-blank character for every line, this way you dont have to worry about formatting your xml for example.
Another convenience you don’t need to escape your quotes within the textblock anymore. In addition with the use of .formatted() you can substitute variables in your text block which comes in handy for templates.

Text Blocks have been released since Java 15.


Where other languages already got easy ways of creating immutable objects Java still was missing out.
But since Java 14 not any more!
With Records they introduce a new special type of class that looks a lot like Kotlin’s Data class. To create a record you can define your class with the record keyword.

For example:

    public record BlogPost(String content, String author, LocalDate publishDate) {}

With this constructor like line the compiler will create a class with auto-generated getters, equals(), hashCode() and an all-args constructor. Furthermore the object will be immutable since all fields are final and thus no setter will be created. If you want to create an additional constructor or add some extra methods to the class you can define it within the record, but the all-args constructor will always be present and don’t forget that all fields are final and have to be set during construction.

Records have been released since Java 16.

Switch expressions

Switch expression are a new way of using switches to assign values to variables. In addition, switch statements have a new way the cases are described as case x → …​ where there’s only 1 line at the right hand of the arrow that will be the effect of the switch case, so no more hussle with breaks.
The big advantage of Switch expressions is that you can use switches to assign values to immutable variables to make your code more robust.

Example of a switch expression:

String input = "bar";
var result = switch(input){
    case "foo" -> "result 1";
    case "bar" -> "result 2";
    default -> throw new IllegalStateException();

In this example I used both addition but it is possible to only use the case x → …​ notation without assigning the result of the switch case directly to a variable.

Switch expressions have been release since Java 14.

Pattern Matching instanceof

Since Java 16 Pattern Matching for instanceof has been released. This feature removes the use of manual casting since doing an instanceof already checks whether it’s possible. So for the scope of your instanceof if-statement you can assign the checked variable to a new variable which is instantly cast towards the desired class if instanceof returns true.

Below is a simple example:

if (a instanceof MyClass x) {
   ...// u can use x now without the need of casting it

The use of the variable x only possible for the scope of the if-statement and no other variables can have the same variable name. It’s a small feature but just like Switch Expressions I think it makes your code a little cleaner.

Pattern Matching for instanceof has been released since Java 16.

Sealed classes

Within Java it’s already possible to restrict access from with access modifiers like private/protected/default/public and is considered a good practice to be as strict as needed for you methods/variables.
Since Java 15 they introduced Sealed classes which enables the developer to limit the use of extending/implementing such sealed classes, it gives a extra layer of protection. With Sealed classes one defines the abstract class/interface which class are permitted to extend/implement it.

For example:

public sealed interface FootballClub permits RealMadrid, Barcelona {
   int getLeaguePosition();
   List<Players> getPlayers();

With the example above classes RealMadrid and Barcelona are allowed to implement the interface FootballClub but basketballteam MiamiHeat isn’t allowed. So with sealed we get a nice way of restricting the usage of abstract classes/interfaces.

For more information about when to use sealed classes check Ties his blog about sealed classes!

Sealed classes have been released since Java 17