Java 17 Features with Practical Examples.
Table of contents
- 1. Sealed Classes (JEP 409)
- 2. Pattern Matching for instanceof (JEP 394)
- 3. Strong Encapsulation of JDK Internals (JEP 403)
- 4. New macOS Rendering Pipeline (JEP 382)
- 5. Foreign Function & Memory API (Incubator) (JEP 412)
- 6. Deprecating the Applet API (JEP 398)
- 7. JVM Performance Improvements (JEP 356, JEP 382)
- 8. New java.lang Methods and Enhancements
- Conclusion
Java 17, released in September 2021, is a significant Long-Term Support (LTS) version of the Java programming language. As an LTS release, it brings several exciting features, performance improvements, and new APIs that improve developer productivity, enhance security, and optimize application performance. This article explores the key features introduced in Java 17 with practical examples.
1. Sealed Classes (JEP 409)
Sealed classes allow developers to define a limited set of subclasses for a given class or interface. This enhances security and maintainability by restricting which classes can inherit from a base class.
Example: Using Sealed Classes
public abstract sealed class Animal permits Dog, Cat {
public abstract void sound();
}
final class Dog extends Animal {
@Override
public void sound() {
System.out.println("Bark");
}
}
final class Cat extends Animal {
@Override
public void sound() {
System.out.println("Meow");
}
}
public class SealedClassesExample {
public static void main(String[] args) {
Animal dog = new Dog();
dog.sound();
Animal cat = new Cat();
cat.sound();
}
}
Output:
Bark
Meow
Here, Animal
is a sealed class, and only Dog
and Cat
can inherit from it. This restricts the possibility of further subclassing, making the design more controlled.
2. Pattern Matching for instanceof
(JEP 394)
Pattern matching simplifies the use of instanceof
by combining the type check and the cast into a single operation. This feature improves readability and reduces boilerplate code.
Example: Pattern Matching with instanceof
public class PatternMatchingExample {
public static void main(String[] args) {
Object obj = "Hello, Java 17";
if (obj instanceof String s) {
System.out.println("String length: " + s.length());
} else {
System.out.println("Not a String");
}
}
}
Output:
String length: 15
In this example, instanceof
is used to check if obj
is an instance of String
and also binds obj
to s
if true, reducing the need for an explicit cast.
3. Strong Encapsulation of JDK Internals (JEP 403)
Java 17 continues the process of strong encapsulation by restricting access to internal APIs in the JDK. This feature strengthens security and promotes better software design by preventing external code from relying on internal, undocumented APIs.
Example: Accessing Internal APIs
In earlier versions, developers could access internal APIs like sun.misc.Unsafe
. However, starting from Java 17, such internal APIs are strongly encapsulated, and access will require the use of --add-opens
or --add-exports
flags at runtime, making it more difficult to rely on internal APIs.
For instance:
java --add-opens java.base/sun.nio.ch=ALL-UNNAMED -jar myapp.jar
While this example doesn't change the code, it shows how Java 17 enforces encapsulation of internal classes and APIs. Developers need to refactor code that depends on these internal APIs.
4. New macOS Rendering Pipeline (JEP 382)
Java 17 introduces a new rendering pipeline for macOS based on Apple's Metal API, replacing the older OpenGL pipeline. This improvement aims to provide better performance, particularly for macOS users.
While this change is mostly internal and handled by the JVM, it benefits applications that rely heavily on graphics and UI, providing improved performance and rendering quality on macOS.
5. Foreign Function & Memory API (Incubator) (JEP 412)
The Foreign Function & Memory API (incubator) allows Java programs to interact with native code and manage native memory more safely and efficiently. This API eliminates the need for Java Native Interface (JNI) and provides a more streamlined, modern approach for working with native code.
Example: Allocating Native Memory with the Foreign API
import jdk.incubator.foreign.*;
public class ForeignFunctionMemoryAPIExample {
public static void main(String[] args) {
try (MemorySegment segment = MemorySegment.allocateNative(100)) {
segment.set(0, (byte) 42); // Writing to native memory
System.out.println("Value at index 0: " + segment.get(0));
}
}
}
Output:
Value at index 0: 42
In this example, the Foreign Function & Memory API
is used to allocate native memory and store a value directly. This API provides an easier and safer way to interact with native memory, eliminating the need for unsafe operations like sun.misc.Unsafe
.
6. Deprecating the Applet API (JEP 398)
Java 17 deprecates the Applet API for removal in a future version. Applets were once used to create interactive web applications but have largely been replaced by more modern web technologies like HTML5, JavaScript, and CSS.
Example: No More Applets
Applets are no longer recommended for use. The deprecation simply means that the Applet API will not be maintained in future versions of Java. If your application uses applets, it is advisable to transition to more modern alternatives.
7. JVM Performance Improvements (JEP 356, JEP 382)
Java 17 brings various performance improvements, including enhancements to the JVM. These improvements make the JVM faster and more efficient, which translates to better application performance.
Example: Improved Performance of G1 Garbage Collector
The G1 garbage collector in Java 17 has been improved to reduce the latency and improve throughput. These changes generally don't require changes to your code, but applications should see improved garbage collection performance.
You can enable the G1 garbage collector with the following JVM flag:
-XX:+UseG1GC
8. New java.lang
Methods and Enhancements
Java 17 introduces several new utility methods to improve the ease of programming and make code more concise.
Example: String.isBlank()
public class StringMethodsExample {
public static void main(String[] args) {
String str = " ";
if (str.isBlank()) {
System.out.println("String is blank");
} else {
System.out.println("String is not blank");
}
}
}
Output:
String is blank
In this example, String.isBlank()
checks if the string is empty or contains only whitespace characters, making it easier to handle string validation.
Conclusion
Java 17 introduces several new features that improve the language, JVM, and developer experience. From sealed classes to pattern matching, foreign function & memory API, and JVM performance improvements, Java 17 offers tools that make code more expressive, efficient, and secure. As an LTS release, Java 17 will be supported for several years, making it a great choice for building long-term applications.
By adopting these new features, developers can write cleaner, more maintainable code and build modern applications that leverage the power of the latest Java platform improvements.
Subscribe to my newsletter
Read articles from Maheshwar Ligade directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Maheshwar Ligade
Maheshwar Ligade
Learner, Love to make things simple, Full Stack Developer, StackOverflower, Passionate about using machine learning, deep learning and AI