Modern Java (17–21): Records, Sealed Classes, Pattern Matching
Modern Java is far more concise than its reputation. Here are the features that define Java 17–21 — records, sealed classes, pattern matching, text blocks, var, and virtual threads — with examples.
Java has a reputation for verbosity that modern Java (versions 17–21) has largely fixed. Records, sealed classes, pattern matching, text blocks, var, and virtual threads make today’s Java dramatically more concise — and they show up increasingly in 2026 interviews. If you learned older Java, these are the upgrades worth adopting.
Here are the features that define modern Java, with examples.
var — local type inference
Since Java 10, var lets the compiler infer a local variable’s type, cutting repetitive declarations:
var names = new ArrayList<String>(); // inferred as ArrayList<String>
var count = 5; // int
It’s still statically typed — the type is fixed at compile time, just not written twice. Use it where the type is obvious.
Records — concise immutable data
The biggest boilerplate-killer. A record auto-generates the constructor, accessors, equals, hashCode, and toString:
record Point(int x, int y) {}
var p = new Point(3, 4);
p.x(); // 3
p.equals(new Point(3, 4)); // true — value equality, free
That one line replaces ~30 lines of a traditional data class. Records are immutable, making them ideal for DTOs and value objects — and they implement equals and hashCode correctly for you.
Sealed classes — a closed set of subtypes
A sealed class or interface restricts who can extend it:
sealed interface Shape permits Circle, Square {}
record Circle(double r) implements Shape {}
record Square(double side) implements Shape {}
Now Shape has exactly two implementations — known and closed. This makes code safer and enables exhaustive pattern matching (below), where the compiler verifies you’ve handled every case.
Pattern matching
Pattern matching streamlines type checks. For instanceof:
// Old
if (obj instanceof String) {
String s = (String) obj; // explicit cast
System.out.println(s.length());
}
// Modern — bind in one step
if (obj instanceof String s) {
System.out.println(s.length());
}
And in switch, especially with sealed types:
String describe(Shape shape) {
return switch (shape) {
case Circle c -> "circle r=" + c.r();
case Square s -> "square " + s.side();
}; // compiler checks all cases are covered (sealed!)
}
Text blocks — multi-line strings
No more escaped, concatenated multi-line strings:
String json = """
{
"name": "Ana",
"active": true
}
""";
Virtual threads — lightweight concurrency
Java 21’s virtual threads let you run millions of cheap threads, making high-concurrency code simple. They’re covered in Java concurrency — one of the most significant modern additions.
Common mistakes
- Overusing
varwhere the inferred type isn’t obvious — it can hurt readability. - Trying to add mutable state to a record — records are immutable by design; use a class if you need mutability.
- Ignoring exhaustiveness — sealed types plus
switchgive you compiler-checked completeness; lean on it. - Sticking to old patterns — manual data classes and explicit casts when records and pattern matching are cleaner.
Where this fits
Modern Java features are Phase 5 of the Java roadmap, complementing streams and lambdas and refining how you write OOP.
They’re used throughout the job-ready Java in Three Months, with the advanced applications — sealed hierarchies for domain modelling, pattern matching at scale, virtual-thread architectures — in Java for Staff Engineers.
Records, sealed classes, and pattern matching turn verbose Java into concise, compiler-checked code — learn them and modern Java feels like a different language.
Frequently asked questions
What are the main new features in modern Java?
Modern Java (17–21) added records (concise immutable data classes), sealed classes (restricting which classes can extend a type), pattern matching for instanceof and switch, text blocks (multi-line strings), the var keyword for local type inference, and virtual threads for lightweight concurrency. Together they make Java far less verbose.
What is a record in Java?
A record is a concise way to declare an immutable data class. Writing record Point(int x, int y) {} automatically generates the constructor, getters, equals, hashCode, and toString. It replaces dozens of lines of boilerplate for classes whose job is simply to hold data.
What is a sealed class in Java?
A sealed class or interface restricts which other classes can extend or implement it, using the permits clause. This gives you a closed, known set of subtypes, which makes code safer and enables exhaustive pattern matching in switch expressions — the compiler can verify you've handled every case.
Should I learn modern Java features as a beginner?
Learn the core language first — classes, collections, exceptions — then adopt modern features as you go. var, records, and text blocks are beginner-friendly and reduce boilerplate immediately. Sealed classes, pattern matching, and virtual threads are worth learning once the fundamentals are solid.