Sealed classes, pattern matching, records, and LTS support—Java 17 features explained with examples you can use on real projects.
Java 17 is a long-term support (LTS) release that many teams still adopt when they leave Java 8 or 11. It is not the bleeding edge today, but it introduced language and library changes that show up constantly in tutorials, Spring Boot baselines, and interview questions.
This article walks through the Java 17 features that change how you write everyday code— with short examples you can paste into a scratch project.
Why Java 17 still matters
Oracle and most vendors treat LTS releases as the default for server deployments: predictable security updates, broad framework support, and migration guides from older LTS lines.
If your employer runs Java 11, moving to 17 is often the next approved step before considering 21 or newer. Learning 17-specific syntax prevents confusion when you read modern open-source code.
Check your runtime:
java -version
You want 17 (or newer) in the feature list.
Sealed classes and interfaces
Sealed types restrict which classes may extend or implement them. That makes domain models exhaustive— useful with pattern matching.
public sealed interface Shape permits Circle, Rectangle {}
public final class Circle implements Shape {
private final double radius;
public Circle(double radius) { this.radius = radius; }
public double radius() { return radius; }
}
public final class Rectangle implements Shape {
private final double w, h;
public Rectangle(double w, double h) { this.w = w; this.h = h; }
}
The compiler knows the full set of Shape implementations, which enables safer switch expressions (see below).
Use sealed hierarchies for closed domains: AST nodes, payment instrument types, protocol messages. Avoid sealing public API types in libraries unless you control all subclasses.
Records for transparent data carriers
Records replace boilerplate data classes:
public record Point(int x, int y) {}
The compiler generates constructor, accessors, equals, hashCode, and toString. Records are implicitly final and work well with JSON mappers and DTO layers.
You can add compact constructors for validation:
public record Email(String value) {
public Email {
if (!value.contains("@")) throw new IllegalArgumentException("invalid email");
}
}
Records are not entities— they are values. Mutable JPA entities should stay regular classes.
Pattern matching for instanceof
Before Java 17, instanceof followed by a cast was noisy:
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.length());
}
Java 16+ (standard in 17) allows:
if (obj instanceof String s) {
System.out.println(s.length());
}
The scoped variable s is available only where the compiler can prove the type holds.
Pattern matching for switch (preview in 17, standardized later)
Java 17 shipped preview pattern switches; subsequent releases refined them. On 17 you may need --enable-preview to experiment. The idea: switch on types and destructure records in one expression.
Conceptual example (syntax may require newer patch levels or preview flags):
static double area(Shape shape) {
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height(); // if you used a record with width/height
default -> throw new IllegalArgumentException();
};
}
Even if your build stays conservative, reading this style helps when upgrading to 21+.
Text blocks for multiline strings
Text blocks delimit JSON, SQL, and HTML snippets without escape-character soup:
String json = """
{
"name": "Ada",
"role": "engineer"
}
""";
Indentation is trimmed intelligently; use \ at the end of a line to suppress trailing newline when needed.
Enhanced pseudo-random number generators
RandomGenerator and implementations like SplittableRandom received API cleanup. Library authors use them for simulations and sharding; application code often still uses ThreadLocalRandom for simple cases:
int dice = ThreadLocalRandom.current().nextInt(1, 7);
Foreign Function & Memory API (incubator in 17)
Java 17 continued incubating the FFM API for calling native code without JNI boilerplate. Most business applications ignore it, but data platforms and drivers adopt it for performance. Watch package names under jdk.incubator.foreign if you explore early builds.
Strong encapsulation of JDK internals
Java 17 tightened access to internal APIs (sun.misc.Unsafe, deep reflective access). Libraries that relied on --illegal-access need updates. When migration guides mention “strong encapsulation,” this is what they mean— run your test suite with default JVM flags before go-live.
Deprecations worth noting
- Security manager — deprecated for removal; do not build new designs around it.
- Applet API — effectively gone from modern deployments.
- Older GC combinations and 32-bit ports fade away— verify vendor support matrices.
Practical migration checklist
- Upgrade build tools — Maven compiler plugin or Gradle toolchains targeting 17.
- Update dependencies — Spring Boot 3.x requires 17+; many libraries dropped Java 8 bytecode.
- Run static analysis — Find internal API usage and deprecated calls.
- Enable preview features only in isolated modules if you experiment with pattern switches.
- Measure performance — GC defaults changed across releases; re-benchmark latency-sensitive services.
Sample Maven compiler snippet:
<properties>
<maven.compiler.release>17</maven.compiler.release>
</properties>
How Java 17 features fit together
Records + sealed types + pattern matching push Java toward algebraic data modeling without leaving the JVM ecosystem. Text blocks and improved NIO helpers reduce friction in integration code. None of these replace solid module boundaries—they express intent more clearly inside them.
FAQ
Should new projects start on 17 or 21?
If your organization standardizes on 21 LTS, start there. If approval processes lag, 17 remains a sane floor with wide library support.
Do records work with Jackson or Gson?
Yes— most JSON libraries map records like ordinary classes with constructor properties.
Will sealed classes break my reflection-heavy framework?
Frameworks that generate subclasses at runtime may conflict with sealed permits. Check release notes for Hibernate, Mockito, and similar tools before migrating.
Is var new in 17?
var local type inference arrived in Java 10. It is still useful alongside 17 features for concise locals without losing readability.
Switch expressions (standard in 14+, idiomatic in 17 codebases)
Arrow switch expressions remove fall-through bugs:
Day day = Day.WEDNESDAY;
String type = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "weekday";
case SATURDAY, SUNDAY -> "weekend";
};
Combine with sealed types so the compiler warns when a case is missing— especially after you add a new Shape implementation.
Helpful JDK library touches in the 17 timeline
While language features grab attention, Java 17 also shipped practical library improvements developers hit weekly:
Stream.toList()(Java 16) — immutable list collector withoutcollect(Collectors.toList()).Optional.isEmpty()— clearer than!optional.isPresent().HexFormat(Java 17) — parse and format hex for crypto and binary protocols.
Example:
List<String> names = people.stream()
.map(Person::name)
.toList();
These small APIs reduce noise when teaching Java 17 because newcomers see modern idioms in day-one examples.
Teaching and interview angles
Interviewers often ask how records differ from Lombok @Data. Answer: records are language-level, immutable by default, and integrate with pattern matching; Lombok generates bytecode at compile time on mutable classes.
Another common question: When would you not upgrade past 11 yet? Legacy app servers, vendor JARs without 17-certified builds, or regulatory validation cycles— but plan the jump; public security support for older lines ends.
Java 17 features are not novelty syntax—they reduce bugs in domain modeling and string handling while aligning the platform with modern language design. Learn sealed types, records, and pattern matching first; they pay off the fastest when you read and write real service code.
Comments
Loading comments…