Java 17 New Features (with Examples)

Java 17 was released on September 14, 2021. Java 17 is an LTS (Long Term Support) release, like Java 11 and Java 8. Oracle will support it for bug fixes, patches and performance enhancements for the next few years.

Spring 6 and Spring boot 3 will have first-class support for Java 17. So it is a good idea to plan for upgrading to Java 17.

We can download Java 17 from this link.

1. List of JEPs in Java 17

The below listed 14 JEPs are part of Java 17.

  1. (JEP-306) Restore Always-Strict Floating-Point Semantics
  2. (JEP-356) Enhanced Pseudo-Random Number Generators
  3. (JEP-382) New macOS Rendering Pipeline
  4. (JEP-391) macOS/AArch64 Port
  5. (JEP-398) Deprecate the Applet API for Removal
  6. (JEP-403) Strongly Encapsulate JDK Internals
  7. (JEP-406) Pattern Matching for switch (Preview)
  8. (JEP-407) Remove RMI Activation
  9. (JEP-409) Sealed Classes
  10. (JEP-410) Remove the Experimental AOT and JIT Compiler
  11. (JEP-411) Deprecate the Security Manager for Removal
  12. (JEP-412) Foreign Function & Memory API (Incubator)
  13. (JEP-414) Vector API (Second Incubator)
  14. (JEP-415) Context-Specific Deserialization Filters

2. Java 17 New Features for Developers

Let us talk about which JEPs directly impact the work that developers do every day.

2.1. Restore Always-Strict Floating-Point Semantics

This JEP is targeted toward scientific calculations that involve floating-point numbers. To guarantee the same calculation result on all platforms, we have been using the keyword strictfp.

The strictfp modifier accomplishes this by representing all intermediate values as IEEE single-precision and double-precision values. However, due to hardware heating issues, it became optional in JDK 1.2.

Today, as the hardwares has evolved and those heating issues are fixed, default floating-point semantics have been changed to consistently strict.

With this change, we do not need to use strictfp keyword, anymore.

2.2. Pattern Matching for Switch (Preview)

This change adds pattern matching for switch statements and expressions. Since this is a preview feature, we need to use ‘–enable-preview‘ option to enable it.

2.2.1. No explicit null checks are needed

Traditional switch statements throw NullPointerException if the selector expression evaluates to null. With this change, we can check for such null expressions as the separate case itself.

if (s == null) {
    System.out.println("oops!");
    return;
}
switch (s) {
    case "Foo", "Bar" -> System.out.println("Great");
    default           -> System.out.println("Ok");
}
switch (s) {
    case null         -> System.out.println("Oops");
    case "Foo", "Bar" -> System.out.println("Great");
    default           -> System.out.println("Ok");
}

2.2.2. Improved instanceof checking

Before Java 16, if we had to write a code that checks the instance type and performed some logic, it was the way:

Object o;
if (o instanceof String) 
{
    String s = (String) o;
    String.format("String %s", s)
} 
else if (o instanceof Integer) 
{
    Integer i = (Integer) o; 
    String.format("int %d", i)
} 
else if (o instanceof Double) 
{
    Double d = (Double) o;
    String.format("double %f", d)
}

In Java 16, we can write the above expression in a much simpler way.

Object o;
if (o instanceof String s) 
{
    String.format("String %s", s)
} 
else if (o instanceof Integer i) 
{
    String.format("int %d", i)
} 
else if (o instanceof Double d) 
{
    String.format("double %f", d)
}

Java 17 takes it to the next level with switch expression. Now we can rewrite the above code as:

Object o;
switch (o) 
{
    case Integer i -> String.format("int %d", i);
    case Double d  -> String.format("double %f", d);
    case String s  -> String.format("String %s", s);
    default        -> o.toString();
}

While the above changes have been made, it has been ensured that all of the old switch expressions must continue to work. You can see all the changes to switch expressions in the JEP webpage.

2.3. Sealed Classes

In Java, by default, there has been no restriction on a class which public interfaces it can implement. From Java 15, we can declare a class or interface sealed class or sealed interface using the modifier ‘sealed‘.

Sealed classes and interfaces restrict which other classes or interfaces may extend or implement them.

public sealed class Account
    permits CurrentAccount, SavingAccount, LoanAccount {
}

It was a preview feature in Java 15 and Java 16. In Java 17, it has become a standard feature with no changes to what was available in Java 16.

Read More : Sealed Classes and Interfaces

2.4. Enhanced Pseudo-Random Number Generators

2.4.1. RandomGenerator

This JEP introduced a new interface called RandomGenerator which aims to make future pseudorandom number generator (PRNG) algorithms easier to implement or use.

With the legacy PRNG classes Random, ThreadLocalRandom, and SplittableRandom, it is difficult to replace any of them in an application with some other algorithm because they do not have any supertype to support runtime changes.

With the introduction of RandomGenerator interface, we can inject any implementing generator class where the client uses RandomGenerator type in the application code. The new classes are:

  • SplittableGenerator – can be split into two objects (the original one and a new one) each of which obeys that same protocol.
  • JumpableGenerator – can easily jump forward, by a moderate amount.
  • LeapableGenerator – can easily not only jump but also leap forward, by a large amount.
  • ArbitrarilyJumpableGenerator – can easily jump forward, by an arbitrary amount, to a distant point in the state cycle.
  • StreamableGenerator – augments the RandomGenerator interface to provide methods that return streams of RandomGenerator objects.

Also, legacy random classes, such as Java.util.Random, SplittableRandom, ThreadLocalRandom and SecureRandom now extend the new RandomGenerator interface.

2.4.2. RandomGeneratorFactory

The RandomGeneratorFactory provides methods for selecting random number generator algorithms. We can choose a particular algorithm by its name and use it for generating random numbers.

The default algorithm is L32X64MixRandom. Following is the list of all supported algorithms:

  • L128X1024MixRandom
  • L128X128MixRandom
  • L128X256MixRandom
  • L32X64MixRandom
  • L64X1024MixRandom
  • L64X128MixRandom
  • L64X128StarStarRandom
  • L64X256MixRandom
  • Random (Legacy)
  • SecureRandom (Legacy)
  • SplittableRandom (Legacy)
  • Xoroshiro128PlusPlus
  • Xoshiro256PlusPlus

The Legecy group represents the old PRNGs. Please note that none of the new implementations are thread-safe while both Java.util.Random and Java.security.SecureRandom are.

RandomGeneratorFactory factory = RandomGeneratorFactory.of("SecureRandom")
RandomGenerator random = factory.create(200L);

//get random numbers
randomGenerator.nextDouble();

2.5. Deprecate the Applet API for Removal

Most of the web browsers have already removed the support for Applets due to security concerns. In Java 9, Applet API was marked deprecated.

Since it has become irrelevant today, Java 17 has marked it for removal.

2.6. Strongly Encapsulate JDK Internals

This JEP strongly encapsulates all internal elements of the JDK, except for critical internal APIs such as sun.misc.Unsafe.

From Java 9 to Java 16, developers were able to access the JDK internal APIs using the flag –illegal-access. Java 17 will ignore the flag, and if the flag is present.

The console will display a message informing the discontinuation of the flag.

2.7. Remove RMI Activation

Remove the Remote Method Invocation (RMI) Activation mechanism while preserving the rest of RMI. It is obsolete and has been deprecated in Java 15.

2.8. Remove the Experimental AOT and JIT Compiler

This JEP removes the experimental Java-based ahead-of-time (AOT) and just-in-time (JIT) compiler introduced in Java 9 and Java 10.

The Graal compiler was made available as an experimental JIT compiler in JDK 10 via JEP 317. Since they were introduced, there was little use of these experimental features, and the effort required to maintain and enhance them was significant.

The developers can still leverage these features using GraalVM.

3. Conclusion

Java 17 has lots of exciting features and a long road of support and commitment. It removes many of the already deprecated APIs from Java.

There is significantly less chance to find any applications which are still using those deprecated features, still, developers must be careful to thoroughly check the application code and dependencies before migrating to Java 17.

As Java 17 is an LTS release, and major popular frameworks (e.g., Spring 6 and Spring Boot 3) will be supporting the new features, it is better to plan for Java 17 migration.

Happy Learning !!

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode