What I Learned Migrating from Java 8 to Java 21
What I Learned Migrating from Java 8 → Java 21?
I realized I was missing out on huge productivity gains
- Verbosity
- Boilerplate
- Thread handling
- String processing
All of this is way better in Java 21.
Pattern Matching with instanceof
No more instanceof + casting drama!
// Java 8
if (obj instanceof String) {
String s = (String) obj;
}
// Java 21
if (obj instanceof String s) {
System.out.println(s.toLowerCase());
}
Text Blocks
Multi-line strings just got cleaner.
// Java 8
String html = "\n" +
" Hello\n" +
"";
// Java 21
String html = """
Hello
""";
Records (Data Classes)
No need to manually create getters, equals(), toString()
//Java 8
public class User {
private final String name;
private final int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// Getters, equals, hashCode, toString...
}
//Java 21
public record User(String name, int age) {}
Switch Expressions (with Arrow)
More powerful, concise, and returns values.
//Java 8
int day = 2;
String dayName;
switch (day) {
case 1: dayName = "Monday"; break;
case 2: dayName = "Tuesday"; break;
default: dayName = "Unknown"; break;
}
//Java 21
int day = 2;
String dayName = switch (day) {
case 1 -> "Monday";
case 2 -> "Tuesday";
default -> "Unknown";
};
Virtual Threads
Massive improvement in concurrency. Handles 1000s of concurrent tasks without heavy threads.
- Lightweight, scalable
- Non-blocking
- Thousands of threads with ease
//Java 8
ExecutorService executor = Executors.newFixedThreadPool(100);
executor.submit(() -> {
// Blocking task
});
//Java 21
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
executor.submit(() -> {
// Blocking task with lightweight thread
});
Sealed Classes
Control subclassing for better API design.
//Java 21
public sealed class Shape permits Circle, Square {}
public final class Circle extends Shape {}
public final class Square extends Shape {}
Why it matters: Great for domain models – keeps hierarchy safe and intentional.