-
Notifications
You must be signed in to change notification settings - Fork 0
Java 14
Release Date: March 17, 2020 | Type: Standard (non-LTS) | Status:
⚠️ End of Life
Java 14 standardizes switch expressions, previews Records (the biggest boilerplate-killer since lambdas) and pattern matching for instanceof, and ships one of the most beloved diagnostic improvements ever: NullPointerExceptions that actually tell you what was null.
mindmap
root((Java 14))
Switch Expressions
Standardized JEP 361
Records
Preview JEP 359
Pattern Matching instanceof
Preview JEP 305
Helpful NPEs
JEP 358
// Now a permanent language feature — no --enable-preview needed
String typeDescription = switch (obj) {
case Integer i -> "int: " + i; // (pattern matching combo comes later, in 21)
default -> "unknown";
};
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};What: A compact syntax for classes that are just immutable data carriers — the compiler generates the constructor, accessors, equals(), hashCode(), and toString() for you.
// Before: ~30 lines of boilerplate
public final class Point {
private final int x;
private final int y;
public Point(int x, int y) { this.x = x; this.y = y; }
public int x() { return x; }
public int y() { return y; }
@Override public boolean equals(Object o) { /* ... */ }
@Override public int hashCode() { /* ... */ }
@Override public String toString() { /* ... */ }
}
// Java 14 record — one line, same guarantees
public record Point(int x, int y) {}
// Usage
Point p = new Point(3, 4);
p.x(); // 3
p.y(); // 4
p.toString(); // "Point[x=3, y=4]"
p.equals(new Point(3, 4)); // true — structural equality, generated for youclassDiagram
class Point {
-int x
-int y
+Point(int x, int y)
+x() int
+y() int
+equals(Object) boolean
+hashCode() int
+toString() String
}
note for Point "All of this generated\nfrom: record Point(int x, int y) {}"
Records can have custom logic too:
public record Range(int start, int end) {
// Compact canonical constructor — runs before field assignment
public Range {
if (start > end) {
throw new IllegalArgumentException("start must be <= end");
}
}
// Extra derived methods are allowed
public int length() {
return end - start;
}
}// Before: cast after every instanceof check
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.length());
}
// Java 14 preview: pattern variable binds automatically
if (obj instanceof String s) {
System.out.println(s.length()); // s is already a String, no cast needed
}
// The pattern variable is even usable in surrounding boolean logic
if (obj instanceof String s && s.length() > 5) {
System.out.println("Long string: " + s);
}What: -XX:+ShowCodeDetailsInExceptionMessages (default-on since Java 15) tells you exactly which variable was null.
// Before Java 14
// Exception in thread "main" java.lang.NullPointerException
// at Main.main(Main.java:8)
// Java 14+
order.getCustomer().getAddress().getCity();
// Exception in thread "main" java.lang.NullPointerException:
// Cannot invoke "Address.getCity()" because the return value of
// "Customer.getAddress()" is null# Enable explicitly on Java 14 (on by default from Java 15+)
java -XX:+ShowCodeDetailsInExceptionMessages -jar app.jarWhy it matters: This single feature has saved countless debugging hours on long method-chain calls (a.getB().getC().getD()) where the stack trace alone couldn't tell you which link in the chain was null.
Low-level JEP allowing memory-mapped byte buffers to target NVM devices — mostly relevant to specialized high-performance storage systems, not typical application code.
✅ Reach for record for DTOs, value objects, and API request/response bodies — huge boilerplate reduction
✅ Combine instanceof pattern matching with && conditions for concise guard clauses
✅ Rely on helpful NPE messages during debugging — don't manually add null checks just to identify the null variable
❌ Don't use records for entities that need mutability or identity semantics (e.g., JPA entities) — records are inherently immutable and final
// Records + pattern matching is a preview of what's coming in Java 21's record patterns
record Point(int x, int y) {}
static String describe(Object obj) {
if (obj instanceof Point p && p.x() == p.y()) {
return "Point on the diagonal";
}
return "Something else";
}