Java 17 Features (LTS)
Dashboard
Topic 23/30
Home › Java 17 Features (LTS)

🔐 Java 17 Features (LTS)

A comprehensive guide to all major features added between Java 9 and Java 17 LTS, including Records, Sealed Classes, and Text Blocks.

1. Records (Java 16)

Records provide a compact syntax for declaring data-carrying classes. They automatically generate constructors, getters, equals(), hashCode(), and toString() methods.

PersonRecord.javaJava
public record PersonRecord(String name, int age) {
    // Compact constructor for validation
    public PersonRecord {
        if (age < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
    }
    
    public static void main(String[] args) {
        PersonRecord p1 = new PersonRecord("Alice", 25);
        System.out.println(p1.name()); // Accessor is name(), not getName()
        System.out.println(p1); // PersonRecord[name=Alice, age=25]
    }
}
RecordWithInterface.javaJava
interface Printable { void print(); }

// Records can implement interfaces, but cannot extend classes
public record PrintableItem(String id) implements Printable {
    @Override
    public void print() {
        System.out.println("Printing item: " + id);
    }
}

2. Sealed Classes (Java 17)

Sealed classes allow you to restrict which classes can extend or implement them. This provides better control over the inheritance hierarchy.

ShapeHierarchy.javaJava
// Sealed interface restricted to specific implementations
public sealed interface Shape permits Circle, Rectangle, Triangle {}

// Subclasses must be final, sealed, or non-sealed
final class Circle implements Shape {
    double radius;
}

final class Rectangle implements Shape {
    double length, width;
}

non-sealed class Triangle implements Shape {
    double base, height;
}

3. Text Blocks (Java 15)

Text blocks simplify the creation of multi-line strings, such as JSON, XML, or SQL queries, by eliminating the need for escape sequences and string concatenation.

TextBlockDemo.javaJava
public class TextBlockDemo {
    public static void main(String[] args) {
        // Multi-line JSON without escaping quotes
        String json = """
            {
                "name": "Java",
                "version": 17,
                "lts": true
            }
            """;
            
        System.out.println(json);
        
        // SQL query spanning multiple lines
        String sql = """
            SELECT id, name, email
            FROM users
            WHERE status = 'ACTIVE'
            ORDER BY created_at DESC
            """;
    }
}

4. Pattern Matching for instanceof (Java 16)

This feature removes the need for explicit casting after an instanceof check by introducing pattern variables.

PatternMatchingDemo.javaJava
public class PatternMatchingDemo {
    public static void main(String[] args) {
        Object obj = "Hello Java 17";
        
        // Old way
        if (obj instanceof String) {
            String s = (String) obj;
            System.out.println("Old Length: " + s.length());
        }
        
        // New way (Pattern matching)
        if (obj instanceof String s) {
            // 's' is automatically casted and bound
            System.out.println("New Length: " + s.length());
        }
    }
}

5. Switch Expressions (Java 14)

Switch expressions modernize the traditional switch statement. They support returning values, arrow syntax, and prevent fall-through automatically.

SwitchExpressionDemo.javaJava
public class SwitchExpressionDemo {
    public static void main(String[] args) {
        String day = "MONDAY";
        
        // Switch expression returning a value
        String typeOfDay = switch (day) {
            case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "Weekday";
            case "SATURDAY", "SUNDAY" -> "Weekend";
            default -> {
                System.out.println("Invalid day");
                yield "Unknown"; // yield returns value from block
            }
        };
        
        System.out.println(day + " is a " + typeOfDay);
    }
}

6. Local Variable Type Inference (var) (Java 10)

The var keyword allows local variable declarations without explicitly stating the type. The compiler infers the type based on the initialization value.

VarDemo.javaJava
import java.util.ArrayList;
import java.util.HashMap;

public class VarDemo {
    public static void main(String[] args) {
        // Reduces verbosity
        var list = new ArrayList<String>(); // Inferred as ArrayList<String>
        var map = new HashMap<Integer, String>(); // Inferred as HashMap<Integer, String>
        
        var message = "Hello Var"; // Inferred as String
        var number = 10; // Inferred as int
        
        for (var item : list) {
            System.out.println(item);
        }
    }
}

7. Helpful NullPointerExceptions (Java 14)

Java 14+ provides detailed information in NPEs, pointing precisely to the object/variable that caused the exception.

Example Exception Message:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "name" is null

8. Collection Factory Methods (Java 9)

Creating immutable collections is now much simpler using factory methods like List.of(), Set.of(), and Map.of().

CollectionFactoryDemo.javaJava
import java.util.List;
import java.util.Map;
import java.util.Set;

public class CollectionFactoryDemo {
    public static void main(String[] args) {
        List<String> list = List.of("A", "B", "C");
        Set<Integer> set = Set.of(1, 2, 3);
        Map<String, Integer> map = Map.of("One", 1, "Two", 2);
        
        System.out.println(list);
    }
}

9. Private Interface Methods (Java 9)

Interfaces can now contain private methods to share code between default methods without exposing them to implementations.

PrivateInterfaceDemo.javaJava
interface Logger {
    default void logInfo(String message) {
        log("INFO: " + message);
    }
    
    default void logError(String message) {
        log("ERROR: " + message);
    }
    
    // Private helper method
    private void log(String message) {
        System.out.println("[Log System] " + message);
    }
}

10. Java Module System (Java 9)

The Java Platform Module System (JPMS) introduced strong encapsulation and better modularity for large applications using module-info.java.

11. Enhanced Pseudo-Random Number Generators (Java 17)

Java 17 provides new interfaces and implementations for PRNGs.

RandomDemo.javaJava
import java.util.random.RandomGeneratorFactory;

public class RandomDemo {
    public static void main(String[] args) {
        var generator = RandomGeneratorFactory.of("L128X256MixRandom").create();
        System.out.println(generator.nextInt(100));
    }
}

12. Feature Timeline Table

Version Major Features Introduced
Java 9 Module System, JShell, Collection Factories, Private Interface Methods
Java 10 Local-Variable Type Inference (var)
Java 11 (LTS) String Methods, HTTP Client API, var in Lambdas
Java 14 Switch Expressions, Helpful NPEs
Java 15 Text Blocks
Java 16 Records, Pattern Matching for instanceof
Java 17 (LTS) Sealed Classes, Enhanced PRNGs