What is New in Java 17?
1 CommentLast Updated on October 21, 2024 by jt
In September 2021, Java 17 was released as the latest LTS (long-term support) replacing Java 11. Now the big question is “What is new in Java 17?”
Java 17 has 14 JDK Enhancement Proposals (JEP) items. Out of those, there are 10 new features, 2 feature removals, and deprecation of 2 features.
In this post, I will cover the key new features of Java 17 applicable to application developers. I will also list the features that have been removed and the deprecated features.
New Features
Some of the key new features of Java 17 for application developers are:
- Sealed classes and interfaces
- Pattern matching for
switch
statements and expressions - New rendering pipeline for MacOS
- New API for accessing large icons
- Pseudo-Random Number Generators
- New
InstantSource
Interface
Sealed Classes and Interfaces
Sealed classes and interfaces (JEP 409) restrict which other classes or interfaces can extend or implement them.
Note: Sealed classes and interfaces were a preview feature in Java 15.
Sealed classes use the permit
keyword to specify the classes and interfaces that can extend or implement them.
Note that only sealed
, final
, and non-sealed
classes can extend a sealed
class.
Sealed classes restrict unnecessary class hierarchy. However, this is not the only motivation. Sealed classes allow you to provide an “escape hatch” for extension. This is the motivation for introducing non-sealed
classes.
package com.example.geometry; public abstract sealed class Shape permits Circle, Rectangle, Square {...} public final class Circle extends Shape {...} public sealed class Rectangle extends Shape {...} public non-sealed class Square extends Shape {...}
In the above code snippet, Shape
is a sealed class. This class permits extension by the Circle
, Rectangle
, and Square
classes.
The code declares the Circle
class as final
and the Rectangle
class as sealed.
The sealed Rectangle
class can also permit other classes like this.
package com.example.geometry; public abstract sealed class Shape permits Circle, Rectangle, Square {...} public final class Circle extends Shape {...} public sealed class Rectangle extends Shape permits TransparentRectangle, FilledRectangle {...} public final class TransparentRectangle extends Rectangle {...} public final class FilledRectangle extends Rectangle {...} public non-sealed class Square extends Shape {...}
In the preceding code snippet, we have two final
classes TransparentRectangle
and FilledRectangle
. Both the classes extend the sealed Rectangle
class.
We also have a non-sealed Square
class. This is the “escape hatch” implying unrestricted subclasses.
Note: One constraint of using a sealed class is that its permitted subclasses must belong to the same module. If it is declared in an unnamed module, it should be in the same package.
Pattern Matching for Switch
Java 17 introduces pattern matching for switch
statements and expressions (JEP 406) as a preview feature.
Java 12 introduced switch
expression as a Preview feature. Later, Java 14 standardized switch
expression. Like any expression, switch
expressions evaluate to a single value and can be used in statements. Switch expressions support “arrow case” labels eliminating the need for break
statements to prevent fall through.
You can use pattern matching to test a switch
expression against a number of patterns, each with a specific action. With pattern matching, you can express complex data-oriented queries concisely and safely.
This code shows a traditional switch
statement . This statement prints the number of letters of elements present in a Status enum
.
enum Status { OPEN, WIP, REVIEW,FIX, CLOSE; } public class SwitchPatternMatching { public int numberOfLetters; public void printNumberOfLetters() { Status status = Status.CLOSE; switch (status) { case WIP: case FIX: numberOfLetters = 3; break; case OPEN: numberOfLetters = 4; break; case CLOSE: numberOfLetters = 5; break; case REVIEW: numberOfLetters = 6; break; default: throw new IllegalStateException("Invalid status: " + status); } System.out.println(numberOfLetters); }
The equivalent code in Java 17 is this.
public void printNumberOfLettersSwitchPattern() { Status status = Status.CLOSE; System.out.println( switch (status) { case WIP,FIX -> 3; case OPEN -> 4; case CLOSE -> 5; default ->throw new IllegalStateException("Invalid status: " + status); } ); }
The preceding code snippet directly returns the number of letters instead of storing it in some variable. Also, the code snippet does not have break
statements to prevent fall through. This is a welcome update as break
statements are error-prone and easy to forget.
In Java 17, you can also test null
in switch
directly, like this.
Status status = null; System.out.println( switch (status) { case null -> System.out.println("Encountered null!"); case WIP,FIX -> 3; case OPEN -> 4; case CLOSE -> 5; default ->throw new IllegalStateException("Invalid status: " + status); } );
Rendering Pipeline for MacOS
The Swing APIs use the Java 2D API for rendering. Prior to Java 17, rendering in MacOS is done using OpenGL APIs. In Java 17, you can use the new Apple Metal accelerated rendering API for macOS.
This is currently disabled by default. Therefore, rendering still uses OpenGL APIs, which are deprecated by Apple but still available.
To enable Metal, set this system property:
-Dsun.java2d.metal=true
As a programmer, your code won’t get affected. This is because Metal or OpenGL is transparent to applications. It is a difference in internal implementation and has no effect on Java APIs.
Note: The metal pipeline requires macOS 10.14.x or later. Earlier Operating System releases will ignore attempts to set the pipeline.
Accessing Large Icons
Java 17 brings a new API to the Swing library to access large icons.
The javax.swing.filechooser.FileSystemView.getSystemIcon(File, int, int)
method is new in JDK 17. This method enables access to higher-quality icons.
Full implementation is there for the Windows platform. However, results on other platforms might vary and enhancement will happen later.
An example is this.
FileSystemView fsv = FileSystemView.getFileSystemView(); Icon icon = fsv.getSystemIcon(new File("application.exe"), 64, 64); JLabel label = new JLabel(icon);
A common use case for this feature is to obtain a higher quality icon for an application executable (exe) file. This icon is suitable for creating a label that can be better scaled in a High DPI environment.
Enhanced Pseudo-Random Number Generators
Java 17 brings in new interface types and implementations for pseudorandom number generators (PRNGs). This new enhancement makes it easier to use various PRNG algorithms interchangeably in applications. It also provides streams of PRNG objects to support stream-based programming.
The API introduces the RandomGenerator
, interface. This interface supplies a uniform API for all existing and new PRNGs. There are several specialized interfaces, such as SplittableRandomGenerator
, JumpableRandomGenerator
, LeapableRandomGenerator
that extend RandomGenerator
to provide specialized methods to generate pseudo-random numbers.
The new RandomGeneratorFactory
class enables to locate and construct instances of RandomGenerator
implementations.
The InstantSource Interface
Java 17 introduces a new InstantSource
interface in the java.time
package. This interface provides an abstraction of java.time.Clock
that only focuses on the current instant and does not refer to the time zone. The primary purpose of this abstraction is to allow plugging in alternate instant sources as and when required.
You can initialize an object that requires the current instant during instantiation by passing an InstantSource
into any method. A dependency injection framework, like Spring is one way to achieve this.
public class MyBean { private InstantSource source; //In Spring this can be autowired for dependency inhection public MyBean(InstantSource source){ this.source=source; } ... public void process(Instant endInstant) { if (source.instant().isAfter(endInstant) { ... } } }
Removed Features
The two key features relevant to application developers that have been removed are:
- Strongly Encapsulate JDK Internals: JDK comes with internal APIs that are not intended for external use. However, over the years the developers of various libraries, frameworks, tools, and applications have used internal elements of the JDK. Doing so can compromise both security and maintainability. These APIs include:
- Some non-public classes, methods, and fields of
java.*
packages. - All classes, methods, and fields of
sun.*
packages. - Most classes, methods, and fields of
com.sun.*
,jdk.*
, andorg.*
packages.
- Some non-public classes, methods, and fields of
- RMI Activation: RMI Activation is an obsolete part of RMI. It has been optional since Java 8. This has been done because distributed systems are currently based on web technology. Moreover, there is evidence that very few existing applications use RMI Activation. In addition, maintaining RMI Activation comes with complexities and incurs continuing maintenance costs.
Deprecated Features
The key features relevant to application developers that have been deprecated are:
- Applet API: Most web browser does not support Java browser plug-ins. Others have plans to stop support. Therefore, Java 17 has deprecated the Applet API for removal.
- Security Manager: Deprecation of the Security Manager and APIs related to it. Java will remove them in a future release. The Java runtime issues a warning at startup if the Security Manager is enabled. You can disable the Security manager:
- Through the command line using
java -Djava.security.manager=disallow...
- Programmatically using
System::setSecurityManager.
- Through the command line using
- Socket Implementation Factory Mechanism: Deprecation of the following static methods for setting the system-wide socket implementation factories:
static void ServerSocket.setSocketFactory(SocketImplFactory fac)
static void Socket.setSocketImplFactory(SocketImplFactory fac)
static void DatagramSocket.setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
- DES and RC4 in Kerberos: The following Kerberos encryption types have been deprecated and disabled by default:
- odes3-hmac-sha1
- orc4-hmac
You as a developer can enable them by setting allow_weak_crypto = true
in the krb5.conf
configuration file.
- JVM tool interface (JVM TI) Heap Functions: The following JVM TI functions have been deprecated:
IterateOverObjectsReachableFromObject
IterateOverReachableObjects
IterateOverHeap
IterateOverInstancesOfClass
A future release will update the preceding functions to return an error indicating that they are no longer supported.
Summary
The new Spring Framework 6 release is based on Java 17. Therefore, If you are a Spring developer, you should migrate to Java 17.
From a commercial point of view, Oracle has finally made Java 17 binaries free to use in production. It is also free to redistribute, at no cost, under the new “Oracle No-Fee Terms and Conditions” (NFTC) license. This move reverses a 2018 decision to charge for Oracle JDK production use.
In this post, I have only discussed the key points that Java 17 brings in. For the complete list, refer to the Release Note.
Paulo Freire
These news are old things in Kotlin