Back to Curriculum

Modern Java Features and Best Practices

📚 Lesson 16 of 16 ⏱️ 50 min

Modern Java Features and Best Practices

50 min

Java continues to evolve with regular releases adding new features that improve developer productivity and code quality. Modern Java (Java 8+) introduced lambdas, streams, modules, records, pattern matching, text blocks, and more. Staying current with Java features helps you write more expressive, maintainable code. Understanding modern features enables you to leverage Java's full power and write idiomatic, modern Java code.

Records (Java 14+, finalized in Java 16) provide a concise way to create immutable data classes. They automatically generate constructors, getters, `equals()`, `hashCode()`, and `toString()` based on components. Records reduce boilerplate for data carrier classes. They're ideal for DTOs, value objects, and data transfer. Understanding records helps you write cleaner, more maintainable code for data classes.

Pattern matching (Java 16+) simplifies conditional logic and type checking. It combines type checking and variable binding in a single expression. Pattern matching works with `instanceof` and `switch` expressions, reducing boilerplate and making code more readable. Future Java versions will expand pattern matching capabilities. Understanding pattern matching helps you write more expressive conditional code.

Text blocks (Java 15+) improve readability of multi-line strings. They use triple quotes (`"""`) and preserve formatting, making JSON, SQL, HTML, and other multi-line strings much more readable. Text blocks automatically handle indentation and escape sequences. Understanding text blocks helps you write more readable multi-line string literals.

Other modern features include sealed classes (restrict inheritance), switch expressions (return values), `var` keyword (local variable type inference), and more. Each Java release adds features that improve developer experience. Understanding modern features helps you write idiomatic, maintainable Java code that leverages the language's full capabilities.

Best practices include staying current with Java features, using modern features appropriately (not everywhere), understanding when features help and when they don't, following Java coding conventions, and writing clean, maintainable code. Modern features should improve code quality, not just use new syntax. Understanding modern Java enables you to write professional, maintainable applications.

Key Concepts

  • Java continues to evolve with new features in each release.
  • Records provide concise syntax for immutable data classes.
  • Pattern matching simplifies conditional logic and type checking.
  • Text blocks improve readability of multi-line strings.
  • Staying current with Java features improves code quality.

Learning Objectives

Master

  • Using records for immutable data classes
  • Understanding pattern matching with instanceof and switch
  • Working with text blocks for multi-line strings
  • Applying modern Java features appropriately

Develop

  • Modern Java programming thinking
  • Understanding when to use modern features
  • Writing idiomatic, maintainable Java code

Tips

  • Use records for immutable data carrier classes.
  • Use pattern matching to simplify type checking and conditional logic.
  • Use text blocks for multi-line strings (JSON, SQL, HTML).
  • Stay current with Java features but use them appropriately.

Common Pitfalls

  • Using modern features everywhere, even when they don't help.
  • Not understanding modern features, using them incorrectly.
  • Ignoring modern features, writing verbose legacy-style code.
  • Mixing old and new styles inconsistently.

Summary

  • Modern Java features improve developer productivity and code quality.
  • Records provide concise syntax for immutable data classes.
  • Pattern matching simplifies conditional logic.
  • Text blocks improve multi-line string readability.
  • Understanding modern Java enables professional development.

Exercise

Demonstrate modern Java features including records, pattern matching, and text blocks.

import java.util.*;
import java.time.*;

// Records (Java 14+)
record Person(String name, int age, String email) {
    // Compact constructor for validation
    public Person {
        if (age < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
        if (email == null || email.trim().isEmpty()) {
            throw new IllegalArgumentException("Email cannot be empty");
        }
    }
    
    // Custom method
    public boolean isAdult() {
        return age >= 18;
    }
}

// Sealed classes and pattern matching (Java 17+)
sealed abstract class Shape permits Circle, Rectangle, Triangle {
    public abstract double area();
}

record Circle(double radius) extends Shape {
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

record Rectangle(double width, double height) extends Shape {
    @Override
    public double area() {
        return width * height;
    }
}

record Triangle(double base, double height) extends Shape {
    @Override
    public double area() {
        return 0.5 * base * height;
    }
}

public class ModernJavaFeatures {
    
    // Pattern matching for instanceof (Java 16+)
    public static String describeObject(Object obj) {
        return switch (obj) {
            case String s -> "String with length: " + s.length();
            case Integer i -> "Integer with value: " + i;
            case List<?> list -> "List with " + list.size() + " elements";
            case null -> "null object";
            default -> "Unknown object: " + obj.getClass().getSimpleName();
        };
    }
    
    // Pattern matching in switch expressions
    public static double calculateArea(Shape shape) {
        return switch (shape) {
            case Circle c -> c.area();
            case Rectangle r -> r.area();
            case Triangle t -> t.area();
        };
    }
    
    // Text blocks (Java 15+)
    public static String generateHTML(Person person) {
        return """
            <div class="person-card">
                <h2>%s</h2>
                <p>Age: %d</p>
                <p>Email: %s</p>
                <p>Status: %s</p>
            </div>
            """.formatted(
                person.name(),
                person.age(),
                person.email(),
                person.isAdult() ? "Adult" : "Minor"
            );
    }
    
    public static void main(String[] args) {
        System.out.println("=== Modern Java Features Demo ===\n");
        
        // Records
        Person alice = new Person("Alice", 25, "alice@example.com");
        Person bob = new Person("Bob", 16, "bob@example.com");
        
        System.out.println("Person records:");
        System.out.println(alice);
        System.out.println(bob);
        System.out.println("Alice is adult: " + alice.isAdult());
        System.out.println("Bob is adult: " + bob.isAdult());
        
        // Pattern matching
        System.out.println("\nPattern matching examples:");
        System.out.println(describeObject("Hello World"));
        System.out.println(describeObject(42));
        System.out.println(describeObject(Arrays.asList(1, 2, 3)));
        
        // Shape calculations
        List<Shape> shapes = Arrays.asList(
            new Circle(5.0),
            new Rectangle(4.0, 6.0),
            new Triangle(3.0, 4.0)
        );
        
        System.out.println("\nShape areas:");
        shapes.forEach(shape -> {
            System.out.printf("%s: %.2f%n", 
                shape.getClass().getSimpleName(), calculateArea(shape));
        });
        
        // Text blocks
        System.out.println("\nGenerated HTML:");
        System.out.println(generateHTML(alice));
        
        // Try-with-resources with pattern matching
        try (var scanner = new Scanner(System.in)) {
            System.out.println("\nEnter your name (or press Enter to skip):");
            String input = scanner.nextLine();
            if (!input.trim().isEmpty()) {
                Person user = new Person(input, 25, "user@example.com");
                System.out.println("Created user: " + user);
            }
        }
    }
}

Code Editor

Output