Upgraded to the Shiny Java 17? Now What?

So your boss told you to upgrade your Spring Boot microservices to Java 17, you did it, all went well! From Java 8 to Java 17, a big jump! What changed? You wonder. What does this upgrade mean for us Java developers in our day to day programming life? Well, let’s take a closer look.
Released on September 15, 2021, Java 17 is the latest LTS (long-term support release) for the Java SE platform. From Java 8 to Java 17, there have been 194 JDK Enhancement Proposals (JEPs) introduced, each of which brings some improvement to the platform. Let’s pick a few to explore.
· Sealed Classes · Switch Expressions · Pattern Matching for Switch (Preview) · Pattern Matching for instanceof · Text Blocks · Record Classes · Meaningful NPE · Introduction of var · New String Methods · Collection Factory Methods
Sealed Classes
Sealed classes or interfaces can restrict which classes or interfaces can extend or implement them. It’s done so by using the sealed modifier, example below:
public abstract sealed class Tree
permits Maple, Willow, Dogwood, Oak{ … }Sealed class gives a tool to better design public APIs. It requires that the listed classes directly extend the sealed class. Compilation error will be thrown if any other classes try to extend the sealed class. Subclasses can also be sealed, which means that it’s possible to define whole hierarchies of fixed alternatives. Permitted classes must be located in the same package as the superclass.
For more information about sealed classes and interfaces, see JEP 409.
Switch Expressions
We’re all familiar with the good old Switch statements in Java:
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;
}Switch has got a facelift since Java 14! The same Switch statement above can be simplified as the following:
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);
}The example below shows Switch being used as an expression to populate a variable. Notice the default block and yield statement.
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
default -> {
String s = day.toString();
int result = s.length();
yield result; }
};Pattern Matching for Switch (Preview)
The old way: switch was very limited, the cases could only test exact equality, and only for values of a few types: numbers, Enum types and Strings.
char grade = 'A';
switch(grade) {
case 'A' :
System.out.println("Excellent!");
break;
case 'B' :
case 'C' :
System.out.println("Well done");
break;
case 'D' :
System.out.println("You passed");
case 'F' :
System.out.println("Better try again");
break;
default :
System.out.println("Invalid grade");
}The new way: this preview feature enhances switch to work on any type and to match on more complex patterns, such as type pattern (Integer i), guard expression (i > 10), even null value.
Object o = 1234;
String formatted = switch (o) {
case Integer i && i > 10 -> String.format("a large Integer %d", i);
case Integer i -> String.format("a small Integer %d", i);
case null -> System.out.println("Null");
default -> "something else"; };Pattern Matching for instanceof
This feature eliminates the need for explicit casts after a type check. The old way, we have to specifically cast the object after calling instanceof:
if (obj instanceof String) {
String s = (String) obj;
// use s
}The new way, less verbose:
if (obj instanceof String s) {
// use s
}Text Blocks
Text containing multiple lines has always been notoriously ugly to express in Java. We are all familiar with such code snippet:
String html = "";
html += "<html>\n";
html += " <body>\n";
html += " <p>Hello, world</p>\n";
html += " </body>\n";
html += "</html>\n";Now we can use multi-line string literals called Text Blocks to make this situation more programmer-friendly:
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";Text Blocks start with """ followed by a new line, and end with """. So much cleaner! New lines and quotes without escaping!
Record Classes
Record Classes introduce a new type declaration to the Java to define immutable data classes. Instead of the usual ceremony with private fields, getters and constructors, it allows us to use a compact syntax. Records can be thought of as nominal tuples.
Old way:
public final class Rectangle {
private final double length;
private final double width;public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}double length() { return this.length; }
double width() { return this.width; }// Implementation of equals() and hashCode(), which specify
// that two record objects are equal if they
// are of the same type and contain equal field values.
public boolean equals...
public int hashCode...// An implementation of toString() that returns a string
// representation of all the record class's fields,
// including their names.
public String toString() {...}
}New way using Record class:
record Rectangle(double length, double width) { }A record class declaration consists of a name; optional type parameters (generic record declarations are supported); a header, which lists the “components” of the record; and a body. A record declaration specifies in a header a description of its contents; the appropriate accessors, constructor, equals, hashCode, and toString methods are created automatically. A record's fields are final because the class is intended to serve as a simple "data carrier".
For more information about record classes, see JEP 395.
Meaningful NPE
We are all used to seeing how NullPointerException gets thrown without clear indication of exactly which object is null, such as the example below.
Exception in thread "main" java.lang.NullPointerException
at Unlucky.method(Unlucky.java:83)Now we can see exactly why that NPE is thrown and how to fix it.
Exception in thread "main" java.lang.NullPointerException:
Cannot invoke "org.w3c.dom.Node.getChildNodes()" because
the return value of "org.w3c.dom.NodeList.item(int)" is null at Unlucky.method(Unlucky.java:83)Introduction of var
Initially introduced in Java 10, var keyword aims to improve developer experience by reducing the ceremony associated with writing Java code, especially with local variable declarations.
Old way:
int length = 0;
...
length = str.length();New way with var:
var length = str.length();Notice: don’t confuse this var with JavaScript’s var keyword. This is not dynamic typing. The type of the declared variables is inferred at compile time. Using var instead of an explicit type makes this piece of code less verbose and easier to read.
New String Methods
Java 11 and 12 introduced the following new String methods, pretty straightforward.
indent
String str = "This is a string.";
String postIndent = str .indent(3); //" This is a string."transform:
String s = "hello".transform(txt-> txt+ " world!"); //"hello world!"
int result = "42".transform(Integer::parseInt); //42repeat:
var text = "test ";
var result = text.repeat(2); // "test test "isBlank:
var text = " ".isBlank(); // truestrip:
assertThat(" f oo ".strip()).isEqualTo("f oo");lines:
"John\nSmith".lines().forEach(System.out::println);
// John
// SmithCollection Factory Methods
Improvements to Collection factory methods were introduced in Java 9. If you haven’t had a chance to catch up, now is the time.
Java is often criticized for its verbosity. Creating a small, unmodifiable collection (say, a set) involves constructing it, storing it in a local variable, and invoking add() on it several times, and then wrapping it. For example:
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
set = Collections.unmodifiableSet(set);Now we can simply use the following to achieve same result:
Set<String> set = Set.of("a", "b", "c");Same feature applies to Collections’ List and Map.
For a comprehensive list of JEPs from Java 8 through Java 17, refer to https://openjdk.java.net/jeps/0.
Feel free to check out some of my other stories on Medium:
Happy coding! Happy crafting!
References:
https://advancedweb.hu/new-language-features-since-java-8-to-17/#record-classes






