Modern Java Features
7 pages · ~5 min✓ Reviewed
Builds on Concurrency.
var and Text Blocks
1. var
var= local type inference from the initializer- Type is static: still strongly typed, not dynamic
var list = new ArrayList<String>()is ArrayList, notList- Want the interface? Declare
List<String>
| Allowed | Fails |
|---|---|
| locals | fields |
| for-loop variables | method parameters |
| lambda parameters | return types |
var x = 1; | var x;, var x = null; |
2. Text Blocks
- Delimiter
"""; line break after the opening one is required - Incidental indent stripped: least-indented line or closing
"""
String s = """ Hi %s \ there\s """.formatted("Ann");
joined line, kept trailing space, filled placeholder
| Gotcha | Effect |
|---|---|
\ at line end | joins lines |
\s | keeps trailing space |
literal """ | must be escaped |
.formatted(args) | fills %s |
var is not Object or dynamic: var x = 1; x = "a"; fails to compile.
Records
1. What a record is
record Point(int x, int y) {}= immutable data carrier- Generated: private final fields, canonical constructor
- Accessors
x()andy(): no get prefix - Also
equals,hashCode,toString - Compact constructor: no parameter list, for validation or normalising
record Range(int lo, int hi) {
Range {
if (lo > hi)
throw new IllegalArgumentException();
}
}2. Rules and comparison
- Implicitly final; cannot extend a class
- No instance fields beyond the components
- Can implement interfaces; static members and extra methods are fine
Sealed Classes and Interfaces
1. A Closed Set of Subtypes
sealed+permitslists the only allowed subtypes- The compiler knows the closed set
- Records are implicitly
final: a natural fit as permitted subtypes
sealed interface Shape permits Circle, Square {}
record Circle(double r) implements Shape {}
record Square(double side) implements Shape {}Shape can have no other implementors
2. Modifiers and Placement
| Modifier | Effect |
|---|---|
final | no further extension |
sealed | continues the restriction |
Switch Expressions and Pattern Matching
1. Switch Expressions
- Switch expression returns a value, uses
->labels - No fall-through, no
break yieldreturns a value from a block- Must be exhaustive: all cases or
default
int n = switch (day) {
case MON, TUE -> 1;
case WED -> { yield 2; }
default -> 0;
};2. Pattern Matching
o instanceof String s && s.length() > 3bindss, no cast- Binding in scope only where the match is definitely true
Virtual Threads
1. What They Are
- Virtual thread (final in Java 21): JVM-scheduled lightweight thread
- Runs on a small pool of carrier platform threads
- Blocks on I/O → unmounts; carrier runs another thread
- So you can have millions of them
- Mounton carrier
- Blocks on I/Ounmount
- Carrier freeruns another
- I/O doneremount
Java 21 Cheat Sheet
1. var and Records
var: locals only, type inferred at compile time- Needs an initializer; never fields or parameters
record R(int a) {}: immutable, accessora()- Compact constructor validates; record is final
- Records can implement interfaces, not extend classes
2. Sealed Types
sealed interface Shape permits Circle, Square {}
record Circle(double r) implements Shape {}
record Square(double side) implements Shape {}records are implicitly final
- Subclass must be final, sealed or non-sealed
- Closed set gives exhaustive switch, no
default
Check yourself
Does var list = new ArrayList<String>(); list = new LinkedList<String>(); compile?
- No:
varinfers the static typeArrayList<String> - Declare
List<String> listto allow both
A record has a List<String> members component. Can t.members().add("z") change it?
- Yes if the list is mutable: records are only shallowly immutable
- Fix:
members = List.copyOf(members);in the compact constructor
switch (o) has case String s and default. What happens when o is null?
- NullPointerException: a pattern switch rejects null