Contents
Java 8:.................................................................................................................... 2
Java 9 :................................................................................................................. 10
Java 10 :............................................................................................................... 14
Java 11................................................................................................................. 15
Java 12:................................................................................................................ 17
Java 13................................................................................................................. 18
Java 14................................................................................................................. 20
Java 15................................................................................................................. 22
Java 16................................................................................................................. 24
Java 18................................................................................................................. 25
Java 19................................................................................................................. 26
Java 20 ................................................................................................................ 29
Java 21 ................................................................................................................ 31
Here is again quick summary of enhancements:.................................................32
This Document details the major enhancements in from Java 8 to Java 21
releases from a developer’s perspective, accompanied by practical code
examples. Document provide a quick look into new features and how they
can be used (which should be studied thoroughly in detail before applying
to production ready code).
I have left out details of enhancements in JVM and Garbage collector as
these are not part of code changes directly.
Java 8:
Major Features with Code Examples:
Lambda Expressions: A concise way to represent anonymous
functions.
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class LambdaExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("John", "Alex", "Mike", "Bob",
"Mary");
System.out.println("Before sorting: " + names);
// Using a lambda expression to sort
Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
System.out.println("After sorting: " + names);
// A more compact lambda for a consumer
names.forEach(name -> System.out.println("Hello, " + name));
}
Functional Interfaces: Interfaces with a single abstract method,
designed for use with lambda expressions.
import java.util.function.Predicate;
import java.util.function.Function;
import java.util.function.Consumer;
public class FunctionalInterfaceExample {
public static void main(String[] args) {
// Predicate: takes one argument, returns boolean
Predicate<Integer> isPositive = x -> x > 0;
System.out.println("Is 5 positive? " + isPositive.test(5)); // true
System.out.println("Is -3 positive? " + isPositive.test(-3)); // false
// Function: takes one argument, returns a result
Function<String, Integer> stringLength = s -> s.length();
System.out.println("Length of 'Java': " +
stringLength.apply("Java")); // 4
// Consumer: takes one argument, returns no result
Consumer<String> printUpperCase = s ->
System.out.println(s.toUpperCase());
printUpperCase.accept("hello world"); // HELLO WORLD
}
Stream API: A powerful API for processing collections of objects in
a functional style.
Java
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamApiExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave",
"Emily", "Frank");
// Filter names starting with 'A' and convert to uppercase
List<String> filteredAndTransformed = names.stream()
.filter(name -> name.startsWith("A"))
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println("Filtered and transformed names: " +
filteredAndTransformed); // [ALICE]
// Count names longer than 4 characters
long count = names.stream()
.filter(name -> name.length() > 4)
.count();
System.out.println("Names longer than 4 characters: " + count); // 3
(Alice, Emily, Frank)
Default Methods in Interfaces: Allowed adding new methods to
interfaces without breaking existing implementations.
Java
interface Vehicle {
void start();
void stop();
// Default method
default void horn() {
System.out.println("Beep beep!");
class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car engine starting...");
@Override
public void stop() {
System.out.println("Car engine stopping...");
public class DefaultMethodExample {
public static void main(String[] args) {
Car myCar = new Car();
myCar.start();
myCar.horn(); // Calls the default method
myCar.stop();
}
Method References: A shorthand for lambda expressions.
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class MethodReferenceExample {
public static void main(String[] args) {
List<String> messages = Arrays.asList("Hello", "World", "Java");
// Using lambda expression
messages.forEach(s -> System.out.println(s));
// Using method reference (equivalent to the above lambda)
messages.forEach(System.out::println);
Optional Class: A container object to avoid NullPointerException.
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
String name = "Alice";
Optional<String> optionalName = Optional.ofNullable(name);
// Using isPresent() and get()
if (optionalName.isPresent()) {
System.out.println("Name: " + optionalName.get()); // Name: Alice
String nullName = null;
Optional<String> optionalNullName =
Optional.ofNullable(nullName);
// Using orElse()
System.out.println("Name (or default): " +
optionalNullName.orElse("Guest")); // Name (or default): Guest
// Using ifPresent()
optionalName.ifPresent(s -> System.out.println("Value is present: " +
s)); // Value is present: Alice
optionalNullName.ifPresent(s -> System.out.println("Value is present:
" + s)); // (nothing printed)
New Date and Time API (java.time): immutable date and time
objects.
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class NewDateTimeApiExample {
public static void main(String[] args) {
// Current date
LocalDate today = LocalDate.now();
System.out.println("Today's date: " + today);
// Current time
LocalTime now = LocalTime.now();
System.out.println("Current time: " + now);
// Specific date and time
LocalDateTime specificDateTime = LocalDateTime.of(2025, 7, 11, 17,
40, 0);
System.out.println("Specific date and time: " + specificDateTime);
// Formatting
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-
MM-dd HH:mm:ss");
String formattedDateTime = specificDateTime.format(formatter);
System.out.println("Formatted date and time: " +
formattedDateTime);
Java 9 :
Java Platform Module System : Modularizes the JDK and
applications, improving security, performance, and maintainability.
To illustrate, a module-info.java file might look like this:
Java
// In a file named module-info.java
module com.example.mymodule {
requires java.base; // Implicitly required, but can be explicit
requires java.net.http; // If using the new HTTP client
exports com.example.mymodule.api; // Exports public API
JShell (REPL Tool): An interactive Read-Eval-Print Loop for quick
code experimentation.
Bash
# From your terminal, type jshell
jshell> System.out.println("Hello, JShell!");
Hello, JShell!
jshell> int x = 10;
x ==> 10
jshell> x * 2
$2 ==> 20
Methods for Immutable Collections: Easier creation of
immutable lists, sets, and maps.
Java
import java.util.List;
import java.util.Set;
import java.util.Map;
public class ImmutableCollectionsExample {
public static void main(String[] args) {
List<String> immutableList = List.of("Apple", "Banana", "Cherry");
System.out.println("Immutable List: " + immutableList);
// immutableList.add("Date"); // Throws
UnsupportedOperationException
Set<Integer> immutableSet = Set.of(1, 2, 3);
System.out.println("Immutable Set: " + immutableSet);
Map<String, String> immutableMap = Map.of("key1", "value1",
"key2", "value2");
System.out.println("Immutable Map: " + immutableMap);
Private Methods in Interfaces: Interfaces can now have private
helper methods for default methods.
Java
interface MyInterface {
default void process() {
init();
System.out.println("Processing...");
cleanup();
private void init() {
System.out.println("Initializing...");
private static void cleanup() {
System.out.println("Cleaning up...");
class MyClass implements MyInterface {
// No need to implement process(), init(), or cleanup()
public class PrivateInterfaceMethodExample {
public static void main(String[] args) {
new MyClass().process();
Java 10 :
Local-Variable Type Inference (var):
import java.util.ArrayList;
import java.util.List;
public class VarKeywordExample {
public static void main(String[] args) {
// Before Java 10
String message = "Hello Java!";
List<String> names = new ArrayList<>();
// Java 10+ with 'var'
var greeting = "Hello Java 10!"; // greeting is inferred as String
var numbers = List.of(1, 2, 3); // numbers is inferred as List<Integer>
System.out.println(greeting);
System.out.println(numbers);
for (var number : numbers) { // 'number' is inferred as Integer
System.out.println(number);
Java 11
HTTP Client : The HTTP Client API
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.io.IOException;
public class HttpClientExample {
public static void main(String[] args) throws IOException,
InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body:\n" + response.body());
String API Enhancements: New useful methods for String
manipulation.
Java
public class StringApiImprovements {
public static void main(String[] args) {
String blankString = " ";
System.out.println("isBlank(): " + blankString.isBlank()); // true
String multiLine = "Line1\nLine2\nLine3";
multiLine.lines().forEach(System.out::println); // Prints each line
separately
String padded = " Hello World ";
System.out.println("strip(): '" + padded.strip() + "'"); // 'Hello World'
System.out.println("stripLeading(): '" + padded.stripLeading() +
"'"); // 'Hello World '
System.out.println("stripTrailing(): '" + padded.stripTrailing() + "'"); //
' Hello World'
System.out.println("Java".repeat(3)); // JavaJavaJava
Java 12:
Switch Expressions : Enhanced switch statements that can return
a value.
public class SwitchExpressionsExample {
public static void main(String[] args) {
String day = "MONDAY";
// As a statement (old way, with break)
switch (day) {
case "MONDAY":
case "FRIDAY":
System.out.println("Working day!");
break;
case "SATURDAY":
case "SUNDAY":
System.out.println("Weekend!");
break;
default:
System.out.println("Midweek day!");
// As an expression
String dayType = switch (day) {
case "MONDAY", "FRIDAY" -> "Working day!";
case "SATURDAY", "SUNDAY" -> "Weekend!";
default -> "Midweek day!";
};
System.out.println(day + " is a " + dayType); // MONDAY is a Working
day!
}}
Java 13
Text Blocks : Multi-line string literals, simplifying JSON, HTML, SQL,
etc.
public class TextBlocksExample {
public static void main(String[] args) {
// Before Text Blocks (cumbersome with escape sequences)
String jsonOld = "{\n" +
" \"name\": \"Alice\",\n" +
" \"age\": 30\n" +
"}";
System.out.println("Old JSON:\n" + jsonOld);
// With Text Blocks
String jsonNew = """
"name": "Bob",
"age": 25
}""";
System.out.println("New JSON:\n" + jsonNew);
// SQL example
String sql = """
SELECT id, name, email
FROM users
WHERE status = 'active'
ORDER BY name;""";
System.out.println("SQL Query:\n" + sql); }}
Java 14
Records: Concise syntax for immutable data classes.
// Define a record
record Point(int x, int y) {
// Records automatically generate constructor, accessors (x(), y()),
// equals(), hashCode(), and toString().
// You can add custom methods or compact constructor here if needed.
public class RecordExample {
public static void main(String[] args) {
Point p1 = new Point(10, 20);
System.out.println("Point p1: " + p1); // Point[x=10, y=20]
System.out.println("X coordinate: " + p1.x()); // 10
System.out.println("Y coordinate: " + p1.y()); // 20
Point p2 = new Point(10, 20);
System.out.println("p1 equals p2: " + p1.equals(p2)); // true
Pattern Matching for instanceof : Simplifies type checking and
casting.
Java
public class PatternMatchingInstanceof {
public static void main(String[] args) {
Object obj = "Hello Java!";
// Before Java 14
if (obj instanceof String) {
String s = (String) obj;
System.out.println("String length (old way): " + s.length());
}
// With Pattern Matching for instanceof
if (obj instanceof String s) { // 's' is the pattern variable
System.out.println("String length (new way): " + s.length());
Object number = 123;
if (number instanceof Integer i && i > 100) {
System.out.println("Integer value greater than 100: " + i);
Java 15
Sealed Classes : Control over which classes can extend or
implement a sealed class/interface.
// Define a sealed interface
sealed interface Shape permits Circle, Square, Triangle {
String getType();
final class Circle implements Shape {
@Override
public String getType() { return "Circle"; }
}
non-sealed class Square implements Shape { // Can be extended by other
classes
@Override
public String getType() { return "Square"; }
sealed class Triangle implements Shape permits EquilateralTriangle {
@Override
public String getType() { return "Triangle"; }
final class EquilateralTriangle extends Triangle {
// No further classes can extend EquilateralTriangle
public class SealedClassExample {
public static void main(String[] args) {
Shape circle = new Circle();
System.out.println(circle.getType());
Shape square = new Square();
System.out.println(square.getType());
}
Java 16
Pattern Matching for switch : Extends pattern matching
capabilities to switch expressions and statements.
Java
public class PatternMatchingSwitchExample {
public static void main(String[] args) {
Object obj = "Hello";
String result = switch (obj) {
case String s -> "It's a String: " + s.length() + " characters long.";
case Integer i -> "It's an Integer: " + i * i;
case null -> "It's null!"; // Explicitly handle null
default -> "Unknown type.";
};
System.out.println(result); // It's a String: 5 characters long.
obj = 42;
result = switch (obj) {
case String s -> "It's a String: " + s.length() + " characters long.";
case Integer i -> "It's an Integer: " + i * i;
case null -> "It's null!";
default -> "Unknown type.";
};
System.out.println(result); // It's an Integer: 1764
Java 18
Simple Web Server: A minimal HTTP server for static files.
Bash
# From your terminal, navigate to a directory with static files
jwebserver
# Or with specific port and directory
jwebserver -p 8080 -d src/main/resources/static
UTF-8 by Default: UTF-8 is now the default charset for the Java SE
Platform. This generally reduces issues with character encoding for
many applications.
Java 19
Virtual Threads : Lightweight threads managed by the JVM,
significantly improving concurrency and scalability.
import java.time.Duration;
import java.util.concurrent.Executors;
public class VirtualThreadExample {
public static void main(String[] args) throws InterruptedException {
// Creating and starting a virtual thread directly
Thread virtualThread = Thread.ofVirtual().start(() -> {
System.out.println("Hello from a virtual thread!");
});
virtualThread.join(); // Wait for the virtual thread to finish
// Using Virtual Threads with an ExecutorService
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10; i++) {
final int taskNum = i;
executor.submit(() -> {
System.out.println("Task " + taskNum + " running on virtual
thread: " + Thread.currentThread());
try {
Thread.sleep(Duration.ofMillis(100)); // Simulate work
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
});
} // Executor automatically shuts down here
System.out.println("All tasks submitted.");
Thread.sleep(Duration.ofSeconds(1)); // Give time for tasks to
complete
}
Record Patterns : Deconstruct record values in instanceof and
switch statements.
record Point(int x, int y) {}
public class RecordPatternsExample {
public static void main(String[] args) {
Object obj = new Point(10, 20);
// Using record pattern with instanceof
if (obj instanceof Point(int x, int y)) {
System.out.println("Object is a Point: x=" + x + ", y=" + y);
// Using record pattern with switch
String description = switch (obj) {
case Point(int x, int y) when x == y -> "Point on diagonal: " + x;
case Point(int x, int y) -> "Point at (" + x + ", " + y + ")";
default -> "Not a point";
};
System.out.println(description);
Java 20 .
Scoped Values : For sharing immutable data within and across
threads.
Example: // TODO
Sequenced Collections: New interfaces for collections with a
defined encounter order.
Java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.SequencedCollection;
public class SequencedCollectionsExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
System.out.println("Original List: " + fruits); // [Apple, Banana,
Cherry]
// Using new SequencedCollection methods (List implements this)
System.out.println("First element: " + fruits.getFirst()); // Apple
System.out.println("Last element: " + fruits.getLast()); // Cherry
fruits.addFirst("Kiwi");
System.out.println("After addFirst: " + fruits); // [Kiwi, Apple, Banana,
Cherry]
fruits.addLast("Grape");
System.out.println("After addLast: " + fruits); // [Kiwi, Apple, Banana,
Cherry, Grape]
String removedFirst = fruits.removeFirst();
System.out.println("Removed first: " + removedFirst + ", List: " +
fruits); // Kiwi, List: [Apple, Banana, Cherry, Grape]
String removedLast = fruits.removeLast();
System.out.println("Removed last: " + removedLast + ", List: " +
fruits); // Grape, List: [Apple, Banana, Cherry]
// Reversed view
SequencedCollection<String> reversedFruits = fruits.reversed();
System.out.println("Reversed view: " + reversedFruits); // [Cherry,
Banana, Apple]
Java 21 .
Example: // TODO
Here is again quick summary of
enhancements:
Version Key Features & Enhancements
🔸 Module System (Project Jigsaw)
🔸 JShell (REPL)
Java 9
🔸 Improved JDK structure
🔸 Reactive Streams API
🔸 var for local variables (type inference)
Java 10 🔸 Application class-data sharing (AppCDS)
🔸 Garbage-Collector Interface
🔸 HttpClient API (standardized)
🔸 var in lambda parameters
Java 11
🔸 Removed Java EE & CORBA modules
🔸 Flight Recorder
🔸 Switch expressions (preview)
Java 12 🔸 JVM Constants API
🔸 Shenandoah GC (experimental)
🔸 Text Blocks (preview)
Java 13 🔸 Dynamic CDS archives
🔸 Reimplementation of legacy socket API
🔸 Records (preview)
🔸 Helpful NullPointerExceptions
Java 14
🔸 Pattern Matching for instanceof
(preview)
Java 15 🔸 Sealed Classes (preview)
🔸 Text Blocks (final)
Version Key Features & Enhancements
🔸 Hidden Classes
🔸 ZGC improvements
🔸 Records (final)
🔸 Pattern Matching for instanceof (2nd
Java 16 preview)
🔸 JEP 394: Strong Encapsulation of JDK
Internals
🔸 Sealed Classes (final)
🔸 Pattern Matching for switch (preview)
Java 17
🔸 New macOS rendering pipeline
🔸 Deprecate and remove RMI Activation
🔸 Simple Web Server (for testing)
Java 18 🔸 UTF-8 as default charset
🔸 Vector API (2nd incubator)
🔸 Virtual Threads (preview)
🔸 Structured Concurrency (preview)
Java 19
🔸 Foreign Function & Memory API
(preview)
🔸 Virtual Threads (2nd preview)
Java 20 🔸 Scoped Values (preview)
🔸 Continued evolution of pattern matching
🔸 Virtual Threads (final)
🔸 Record Patterns (final)
🔸 Pattern Matching for switch (final)
Java 21
🔸 Sequenced Collections
🔸 String Templates
🔸 Foreign Function & Memory API (final)