What’s new in Java 17

Kannappan Chidambaram
5 min readJan 10, 2022

With the recent release of Java 17 LTS release, many new language features are added to JDK. Let's explore each new features added in JDK17 in brief.

Sealed Classes — JDK 17 JEP 409

Added as preview in JDK16, sealed classes and interfaces restrict which other classes need to implement or extend them. It allows author of the class or interface to control which code is responsible for extending or implementing them.

  • provides a more declarative way than access modifiers to restrict the use of a superclass.
  • support future enhancements in pattern matching to avoid exhaustive analysis of patterns.

A class is sealed by adding sealed modifier to its declaration and permits clause specifies classes that are permitted to extend sealed class, sealed class and permitted subclass needs to be in same module, if module is not defined, it needs to be same package. sub classes extending sealed class can be either final or another sealed class or non-sealed classes, like in below example.

package com.domain.shapes;

public abstract sealed class Shape permits Circle,Square, Rectangle {
}

public final class Circle extends Shape {
}

public non-sealed class Square extends Shape {
}

public sealed class Rectangle extends Shape permits TransparentRectange,OpaqueRectangle {
}

public final class OpaqueRectangle extends Rectangle {
}

public final class TransparentRectange extends Rectangle {
}

Text Blocks — JDK 17 JEP 378

Multi-line String literal that can be represented in quote without having to deal with most escape sequences.

consider the below example of populating of html string in string variable, before text blocks, we need to escape with new line escapes and concatenation for below multiple line spanning string, manully processing the below string can lead to error-prone.

String html = "<html>\n" +
"<body>\n"+
"<p>Test</p>\n"+
"</body>\n"+
"</html>\n";

with text block in JDK17, above string can be rewritten with text block like below , it is defined with three double quotes and it can span in multiple lines, text block automatically formats the strings in predictable way, and gives developer control over the format needed-

String html = """
<html>
<body>
<p>Test</p>
</body>
</html>
""";

Pattern Matching for instanceof — JDK 16 JEP 394

Pattern matching allows the condition extraction of components from objects to be expressed more concisely and safely

Lets consider the below example, here we are first testing whether obj is a string, then declaration of string variable s and then type casting obj to string into variable s.

if(obj instanceof String) {
String s = (String) obj;
}

with JDK17, pattern matching for instanceof feature, we can reduce code to single line like below, i.e, variable s is created only when obj is instance of String , and type casting obj to string happens automatically

if(obj instanceof String s) {
//use s
} else {
// s is out of scope here
}

Switch Expressions (JDK 14 JEP 361) -

Extends switch so it can be used as switch statement or expression.

Both forms can use either

raditional case ... : labels //with fall through
New case ... -> labels //without fall through

new statement “yield” added for yielding (Returning) an value from switch expression.

For eg , with traditional switch expression in java,

int  numLetters;
switch(day)
{
case MONDAY:
case FRIDAY:
case SUNDAY:
numLetters = 6;
break;
case TUESDAY:
numLetters = 7;
break;
case THURSDAY:
case SATURDAY:
numLetters = 8;
case WEDNESDAY:
numLetters = 9;
break;
default:
throw new IllegalArgumentException(" Not a day: " + day);
}
return numLetters;

Using switch expressions, it returns value, no extra variable needed as in above case and also multiple constants separated by comma can be defined in each branch.

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

Pattern Matching for switch Preview — JDK 17 JEP 406

Pattern matching on switch allows an expression to be tested against a number of patterns, each with specific action.

  • allow patterns to be appear in case labels
  • introduces case null statement

current switch statements allows to work on few types — Numeric, Enum and Strings. If we want to use patterns to check for certain conditions, then chain of if else condition blocks are used like in the below.

static String formatter(Object o){
String formatted = "unknown";
if(o instanceof Integer i){
formatted = String.format("int %d",i);
} else if ( o instanceof Long l){
formatted = String.format("long %d",l);
}
return formatted;
}

with new feature “pattern matching for switch” , chain of if-else conditions are replaced with switch expressions as it checks for the pattern.

static String formatter(Object o){
return switch(o){
case null -> "null";
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
default -> o.toString();
};
}

Records — JDK 16 JEP 395

Records provide a compact syntax for declaring classes which are transparent holders for shallowly immutable data.

JDK 16 added records feature , which saved developers that need to deal with boilerplate codes (such as getter/setter, constructor , equals and hashcode implementations)

Records are build on components, components are compiled as final fields like in below , they are only fields that can have in record, we cannot add any instance fields in record.

record range(int start, int end){}
  • Record is final class, no state can be added to record class through inheritance.
public final class point{
final int x;
final int y;
}

Previously before JDK 16 , final class would have been written in below apporach.

public final class point{
final int x;
final int y;

public point(int x, int y) {
this.x = x;
this.y = y;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
point point = (point) o;
return x == point.x && y == point.y;
}

@Override
public int hashCode() {
return Objects.hash(x, y);
}

@Override
public String toString() {
return "point{" +
"x=" + x +
", y=" + y +
'}';
}

public int x(){
return x;
}

public int y(){
return y;
}
}

With JDK17, Instead of class we say records, that compiler can make sure our records will get all required methods without have not explicity define it, records are not just eliminating the boilerplate codes. records represent improvement in the platform

--

--

Kannappan Chidambaram

Passionate about programming, currently working as technical analyst at Ideas2IT Technologies