Explore Java's powerful deconstruction patterns including Records, Pattern Matching, and advanced destructuring techniques.
Table of Contents
- Record Deconstruction
- Pattern Matching with instanceof
- Switch Expression Patterns
- Custom Deconstruction Patterns
- Advanced Nesting Patterns
- Real-World Use Cases
Record Deconstruction
1. Basic Record Deconstruction
// Basic record definition public record Person(String name, int age, String email) { // Compact constructor with validation public Person { if (age < 0) { throw new IllegalArgumentException("Age cannot be negative"); } if (email != null && !email.contains("@")) { throw new IllegalArgumentException("Invalid email format"); } } // Static factory method public static Person of(String name, int age) { return new Person(name, age, null); } } // Deconstruction examples public class RecordDeconstruction { public static void main(String[] args) { // Create record instance Person person = new Person("Alice", 30, "[email protected]"); // Traditional accessors String name = person.name(); int age = person.age(); String email = person.email(); // Deconstruction in Java 16+ (conceptual - not actual syntax) // This demonstrates the concept that will be available in future versions System.out.println("Name: " + name + ", Age: " + age + ", Email: " + email); } // Method that demonstrates deconstruction concept public static void processPerson(Person person) { // Imagine future Java version supporting this: // Person(String name, int age, String email) = person; // Current approach - using accessors String name = person.name(); int age = person.age(); String email = person.email(); System.out.printf("Processing %s (%d years old) - %s%n", name, age, email); } } 2. Advanced Record Patterns
// Complex record with nested records public record Address(String street, String city, String zipCode, String country) { public Address { if (street == null || street.isBlank()) { throw new IllegalArgumentException("Street cannot be empty"); } } public String format() { return String.format("%s, %s %s, %s", street, city, zipCode, country); } } public record Employee( String id, Person person, Address address, String department, double salary ) { public Employee { if (salary < 0) { throw new IllegalArgumentException("Salary cannot be negative"); } } public boolean isRemote() { return address.city().equals("REMOTE"); } } // Record pattern matching examples public class AdvancedRecordPatterns { // Traditional approach to extracting data public static void printEmployeeInfoTraditional(Employee employee) { Person person = employee.person(); Address address = employee.address(); String name = person.name(); String city = address.city(); System.out.printf("Employee %s works in %s%n", name, city); } // Using method to simulate pattern matching public static void extractEmployeeData(Employee employee) { // Simulating what pattern matching might look like String id = employee.id(); Person person = employee.person(); Address address = employee.address(); String department = employee.department(); double salary = employee.salary(); // Process extracted data if (salary > 100000) { System.out.printf("High earner: %s in %s%n", person.name(), department); } } // Process multiple records public static void processEmployees(List<Employee> employees) { for (Employee emp : employees) { // Extract nested data String empName = emp.person().name(); String empCity = emp.address().city(); double empSalary = emp.salary(); System.out.printf("%s in %s earns $%.2f%n", empName, empCity, empSalary); } } } Pattern Matching with instanceof
3. Type Pattern Matching
// Hierarchy of shapes public sealed interface Shape permits Circle, Rectangle, Triangle, CompositeShape { double area(); double perimeter(); } public record Circle(double radius) implements Shape { public Circle { if (radius <= 0) { throw new IllegalArgumentException("Radius must be positive"); } } @Override public double area() { return Math.PI * radius * radius; } @Override public double perimeter() { return 2 * Math.PI * radius; } } public record Rectangle(double width, double height) implements Shape { public Rectangle { if (width <= 0 || height <= 0) { throw new IllegalArgumentException("Dimensions must be positive"); } } @Override public double area() { return width * height; } @Override public double perimeter() { return 2 * (width + height); } public boolean isSquare() { return width == height; } } public record Triangle(double side1, double side2, double side3) implements Shape { public Triangle { if (side1 <= 0 || side2 <= 0 || side3 <= 0) { throw new IllegalArgumentException("Sides must be positive"); } // Triangle inequality validation if (side1 + side2 <= side3 || side1 + side3 <= side2 || side2 + side3 <= side1) { throw new IllegalArgumentException("Invalid triangle sides"); } } @Override public double area() { // Heron's formula double s = perimeter() / 2; return Math.sqrt(s * (s - side1) * (s - side2) * (s - side3)); } @Override public double perimeter() { return side1 + side2 + side3; } } public record CompositeShape(String name, List<Shape> components) implements Shape { public CompositeShape { if (components == null || components.isEmpty()) { throw new IllegalArgumentException("Components cannot be empty"); } } @Override public double area() { return components.stream() .mapToDouble(Shape::area) .sum(); } @Override public double perimeter() { // For composite shapes, perimeter might not be well-defined return components.stream() .mapToDouble(Shape::perimeter) .sum(); } } // Pattern matching with instanceof public class InstanceOfPatternMatching { // Traditional instanceof with casting public static String describeShapeTraditional(Shape shape) { if (shape instanceof Circle) { Circle circle = (Circle) shape; return String.format("Circle with radius %.2f (area: %.2f)", circle.radius(), circle.area()); } else if (shape instanceof Rectangle) { Rectangle rect = (Rectangle) shape; return String.format("Rectangle %.2f x %.2f (area: %.2f)", rect.width(), rect.height(), rect.area()); } else if (shape instanceof Triangle) { Triangle tri = (Triangle) shape; return String.format("Triangle with sides %.2f, %.2f, %.2f", tri.side1(), tri.side2(), tri.side3()); } else { return "Unknown shape"; } } // Modern pattern matching with instanceof (Java 16+) public static String describeShapeModern(Shape shape) { if (shape instanceof Circle circle) { return String.format("Circle with radius %.2f (area: %.2f)", circle.radius(), circle.area()); } else if (shape instanceof Rectangle rect) { String type = rect.isSquare() ? "Square" : "Rectangle"; return String.format("%s %.2f x %.2f (area: %.2f)", type, rect.width(), rect.height(), rect.area()); } else if (shape instanceof Triangle tri) { return String.format("Triangle with sides %.2f, %.2f, %.2f (perimeter: %.2f)", tri.side1(), tri.side2(), tri.side3(), tri.perimeter()); } else if (shape instanceof CompositeShape comp) { return String.format("Composite shape '%s' with %d components (total area: %.2f)", comp.name(), comp.components().size(), comp.area()); } else { return "Unknown shape"; } } // Pattern matching with additional conditions public static String analyzeShape(Shape shape) { if (shape instanceof Circle circle && circle.radius() > 10) { return "Large circle: " + circle.radius(); } else if (shape instanceof Rectangle rect && rect.isSquare()) { return "Square with side: " + rect.width(); } else if (shape instanceof Triangle tri) { if (tri.side1() == tri.side2() && tri.side2() == tri.side3()) { return "Equilateral triangle"; } else if (tri.side1() == tri.side2() || tri.side1() == tri.side3() || tri.side2() == tri.side3()) { return "Isosceles triangle"; } else { return "Scalene triangle"; } } else { return "Other shape"; } } // Processing collections with pattern matching public static void processShapes(List<Shape> shapes) { for (Shape shape : shapes) { if (shape instanceof Circle circle) { System.out.printf("Processing circle (r=%.2f)%n", circle.radius()); } else if (shape instanceof Rectangle rect) { System.out.printf("Processing rectangle (%.2fx%.2f)%n", rect.width(), rect.height()); } // Additional processing... } } } Switch Expression Patterns
4. Enhanced Switch Patterns
// Domain models for different types of events public sealed interface Event permits UserEvent, SystemEvent, AuditEvent, ErrorEvent { String id(); Instant timestamp(); String source(); } public record UserEvent( String id, Instant timestamp, String source, String userId, String action, Map<String, Object> metadata ) implements Event {} public record SystemEvent( String id, Instant timestamp, String source, String component, String operation, Duration duration ) implements Event {} public record AuditEvent( String id, Instant timestamp, String source, String auditor, String target, String action, boolean success ) implements Event {} public record ErrorEvent( String id, Instant timestamp, String source, String errorType, String message, String stackTrace, Severity severity ) implements Event { public enum Severity { LOW, MEDIUM, HIGH, CRITICAL } } // Switch pattern matching examples public class SwitchPatternMatching { // Traditional switch statement public static String processEventTraditional(Event event) { if (event instanceof UserEvent) { UserEvent userEvent = (UserEvent) event; return "User action: " + userEvent.action(); } else if (event instanceof SystemEvent) { SystemEvent sysEvent = (SystemEvent) event; return "System operation: " + sysEvent.operation(); } else if (event instanceof AuditEvent) { AuditEvent auditEvent = (AuditEvent) event; return "Audit: " + auditEvent.action() + " - " + (auditEvent.success() ? "SUCCESS" : "FAILED"); } else if (event instanceof ErrorEvent) { ErrorEvent errorEvent = (ErrorEvent) event; return "Error: " + errorEvent.message(); } else { return "Unknown event"; } } // Modern switch expression with pattern matching (Java 21+ preview) public static String processEventModern(Event event) { return switch (event) { case UserEvent userEvent -> String.format("User %s performed: %s", userEvent.userId(), userEvent.action()); case SystemEvent sysEvent when sysEvent.duration().toMinutes() > 5 -> String.format("Long system operation: %s took %d minutes", sysEvent.operation(), sysEvent.duration().toMinutes()); case SystemEvent sysEvent -> String.format("System operation: %s completed", sysEvent.operation()); case AuditEvent auditEvent when !auditEvent.success() -> String.format("AUDIT FAILURE: %s on %s", auditEvent.action(), auditEvent.target()); case AuditEvent auditEvent -> String.format("Audit: %s completed successfully", auditEvent.action()); case ErrorEvent errorEvent when errorEvent.severity() == ErrorEvent.Severity.CRITICAL -> String.format("CRITICAL ERROR: %s - %s", errorEvent.errorType(), errorEvent.message()); case ErrorEvent errorEvent -> String.format("Error [%s]: %s", errorEvent.severity(), errorEvent.message()); default -> "Unknown event type"; }; } // Complex pattern matching with nested extraction public static void analyzeEvents(List<Event> events) { for (Event event : events) { String analysis = switch (event) { case UserEvent(var id, var timestamp, var source, var userId, var action, var metadata) -> { if (action.equals("LOGIN")) { yield String.format("User %s logged in from %s", userId, source); } else if (action.equals("LOGOUT")) { yield String.format("User %s logged out", userId); } else { yield String.format("User %s performed %s", userId, action); } } case SystemEvent(var id, var timestamp, var source, var component, var operation, var duration) when duration.toSeconds() > 60 -> { yield String.format("Slow system operation: %s.%s took %d seconds", component, operation, duration.toSeconds()); } case ErrorEvent(var id, var timestamp, var source, var errorType, var message, var stackTrace, var severity) when severity == ErrorEvent.Severity.HIGH -> { yield String.format("High severity error in %s: %s", source, message); } case null -> "Null event encountered"; default -> "Event type: " + event.getClass().getSimpleName(); }; System.out.println(analysis); } } // Pattern matching with guards and complex conditions public static String categorizeEvent(Event event) { return switch (event) { case UserEvent user when user.action().contains("DELETE") -> "DESTRUCTIVE_USER_ACTION"; case UserEvent user when user.action().contains("CREATE") -> "CREATIVE_USER_ACTION"; case SystemEvent sys when sys.duration().toMillis() > 5000 -> "LONG_RUNNING_SYSTEM_OPERATION"; case SystemEvent sys when sys.component().equals("DATABASE") -> "DATABASE_OPERATION"; case AuditEvent audit when !audit.success() -> "AUDIT_FAILURE"; case ErrorEvent error when error.severity() == ErrorEvent.Severity.CRITICAL -> "CRITICAL_FAILURE"; case ErrorEvent error when error.message().contains("timeout") -> "TIMEOUT_ERROR"; default -> "STANDARD_EVENT"; }; } } Custom Deconstruction Patterns
5. Creating Custom Destructuring Methods
// Traditional class with custom deconstruction public class ComplexNumber { private final double real; private final double imaginary; public ComplexNumber(double real, double imaginary) { this.real = real; this.imaginary = imaginary; } // Traditional getters public double getReal() { return real; } public double getImaginary() { return imaginary; } // Custom deconstruction method public ComplexParts deconstruct() { return new ComplexParts(real, imaginary); } // Static factory method for construction public static ComplexNumber of(double real, double imaginary) { return new ComplexNumber(real, imaginary); } // Record for deconstructed parts public record ComplexParts(double real, double imaginary) { public ComplexNumber toComplexNumber() { return new ComplexNumber(real, imaginary); } } @Override public String toString() { return String.format("%.2f + %.2fi", real, imaginary); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof ComplexNumber that)) return false; return Double.compare(that.real, real) == 0 && Double.compare(that.imaginary, imaginary) == 0; } @Override public int hashCode() { return Objects.hash(real, imaginary); } } // Custom container with deconstruction support public class Pair<A, B> { private final A first; private final B second; public Pair(A first, B second) { this.first = first; this.second = second; } public A first() { return first; } public B second() { return second; } // Deconstruction method public Object[] deconstruct() { return new Object[]{first, second}; } // Pattern matching support method public boolean matches(Class<A> firstType, Class<B> secondType) { return firstType.isInstance(first) && secondType.isInstance(second); } @Override public String toString() { return String.format("Pair[%s, %s]", first, second); } // Static factory public static <A, B> Pair<A, B> of(A first, B second) { return new Pair<>(first, second); } } // Custom deconstruction examples public class CustomDeconstruction { public static void processComplexNumber(ComplexNumber cn) { // Traditional approach double real = cn.getReal(); double imaginary = cn.getImaginary(); // Using custom deconstruction ComplexNumber.ComplexParts parts = cn.deconstruct(); double r = parts.real(); double i = parts.imaginary(); System.out.printf("Complex number: %.2f + %.2fi%n", r, i); } public static void processPair(Pair<?, ?> pair) { Object[] components = pair.deconstruct(); Object first = components[0]; Object second = components[1]; System.out.printf("Pair contains: %s and %s%n", first, second); // Type-safe processing with pattern matching simulation if (pair.matches(String.class, Integer.class)) { @SuppressWarnings("unchecked") Pair<String, Integer> stringIntPair = (Pair<String, Integer>) pair; processStringIntPair(stringIntPair); } } private static void processStringIntPair(Pair<String, Integer> pair) { String name = pair.first(); Integer value = pair.second(); System.out.printf("String-Integer pair: %s -> %d%n", name, value); } // Advanced deconstruction with multiple return values public static class DataPoint { private final String label; private final double[] values; private final Map<String, Object> metadata; public DataPoint(String label, double[] values, Map<String, Object> metadata) { this.label = label; this.values = values.clone(); // Defensive copy this.metadata = new HashMap<>(metadata); } // Multiple deconstruction options public BasicComponents deconstructBasic() { return new BasicComponents(label, values.length); } public FullComponents deconstructFull() { return new FullComponents(label, values, metadata); } public record BasicComponents(String label, int valueCount) {} public record FullComponents(String label, double[] values, Map<String, Object> metadata) {} public String label() { return label; } public double[] values() { return values.clone(); } // Defensive copy public Map<String, Object> metadata() { return new HashMap<>(metadata); } } } Advanced Nesting Patterns
6. Complex Nested Pattern Matching
// Complex domain model for e-commerce public record Customer( String id, String name, Address address, List<Order> orders, CustomerPreferences preferences ) { public Customer { if (orders == null) orders = new ArrayList<>(); if (preferences == null) preferences = new CustomerPreferences(); } public boolean hasOrders() { return !orders.isEmpty(); } } public record CustomerPreferences( boolean emailNotifications, boolean smsNotifications, String currency, String language, List<String> favoriteCategories ) { public CustomerPreferences { if (favoriteCategories == null) favoriteCategories = new ArrayList<>(); if (currency == null) currency = "USD"; if (language == null) language = "en"; } } public record Order( String orderId, Instant orderDate, List<OrderItem> items, OrderStatus status, PaymentInfo payment, ShippingInfo shipping ) { public double totalAmount() { return items.stream() .mapToDouble(item -> item.price() * item.quantity()) .sum(); } public boolean isShippable() { return status == OrderStatus.CONFIRMED || status == OrderStatus.PROCESSING; } } public record OrderItem( String productId, String productName, int quantity, double price, Map<String, String> attributes ) { public double subtotal() { return price * quantity; } } public enum OrderStatus { PENDING, CONFIRMED, PROCESSING, SHIPPED, DELIVERED, CANCELLED } public record PaymentInfo( String paymentMethod, String transactionId, boolean paid, Instant paymentDate ) {} public record ShippingInfo( Address shippingAddress, String carrier, String trackingNumber, Instant estimatedDelivery ) {} // Advanced nested pattern matching public class NestedPatternMatching { // Process customer with nested pattern matching simulation public static void analyzeCustomer(Customer customer) { // Extract nested data String customerName = customer.name(); Address address = customer.address(); List<Order> orders = customer.orders(); CustomerPreferences prefs = customer.preferences(); // Process address String city = address.city(); String country = address.country(); // Process preferences boolean wantsEmails = prefs.emailNotifications(); String preferredCurrency = prefs.currency(); System.out.printf("Customer %s in %s, %s%n", customerName, city, country); System.out.printf("Preferences: email=%s, currency=%s%n", wantsEmails, preferredCurrency); // Process orders with nested data for (Order order : orders) { processOrder(order); } } private static void processOrder(Order order) { String orderId = order.orderId(); OrderStatus status = order.status(); double total = order.totalAmount(); List<OrderItem> items = order.items(); PaymentInfo payment = order.payment(); ShippingInfo shipping = order.shipping(); System.out.printf("Order %s: %s, Total: $%.2f%n", orderId, status, total); // Process payment info if (payment.paid()) { System.out.printf(" Paid via %s on %s%n", payment.paymentMethod(), payment.paymentDate()); } // Process shipping if applicable if (order.isShippable() && shipping != null) { System.out.printf(" Shipping to %s via %s%n", shipping.shippingAddress().city(), shipping.carrier()); } // Process items for (OrderItem item : items) { processOrderItem(item); } } private static void processOrderItem(OrderItem item) { String productName = item.productName(); int quantity = item.quantity(); double price = item.price(); double subtotal = item.subtotal(); System.out.printf(" %d x %s @ $%.2f = $%.2f%n", quantity, productName, price, subtotal); } // Complex analysis with multiple levels of nesting public static CustomerReport generateCustomerReport(Customer customer) { String customerId = customer.id(); String customerName = customer.name(); Address address = customer.address(); List<Order> orders = customer.orders(); // Calculate statistics long totalOrders = orders.size(); double totalSpent = orders.stream() .mapToDouble(Order::totalAmount) .sum(); double averageOrderValue = totalOrders > 0 ? totalSpent / totalOrders : 0; // Analyze order status distribution Map<OrderStatus, Long> statusCount = orders.stream() .collect(Collectors.groupingBy(Order::status, Collectors.counting())); // Find most expensive order Optional<Order> mostExpensiveOrder = orders.stream() .max(Comparator.comparing(Order::totalAmount)); return new CustomerReport( customerId, customerName, address.city(), address.country(), totalOrders, totalSpent, averageOrderValue, statusCount, mostExpensiveOrder.map(Order::totalAmount).orElse(0.0) ); } public record CustomerReport( String customerId, String customerName, String city, String country, long totalOrders, double totalSpent, double averageOrderValue, Map<OrderStatus, Long> orderStatusDistribution, double mostExpensiveOrder ) { public void print() { System.out.printf("Customer Report: %s (%s)%n", customerName, customerId); System.out.printf("Location: %s, %s%n", city, country); System.out.printf("Orders: %d, Total Spent: $%.2f, Avg Order: $%.2f%n", totalOrders, totalSpent, averageOrderValue); System.out.println("Order Status Distribution:"); orderStatusDistribution.forEach((status, count) -> System.out.printf(" %s: %d%n", status, count)); System.out.printf("Most Expensive Order: $%.2f%n", mostExpensiveOrder); } } // Pattern matching with collections public static void processCustomerOrders(List<Customer> customers) { for (Customer customer : customers) { // Extract customer data String customerName = customer.name(); List<Order> orders = customer.orders(); // Filter and process orders List<Order> recentOrders = orders.stream() .filter(order -> order.orderDate().isAfter(Instant.now().minusSeconds(30 * 24 * 60 * 60))) .collect(Collectors.toList()); List<Order> highValueOrders = recentOrders.stream() .filter(order -> order.totalAmount() > 1000) .collect(Collectors.toList()); // Process high-value orders for (Order order : highValueOrders) { processHighValueOrder(customerName, order); } } } private static void processHighValueOrder(String customerName, Order order) { System.out.printf("High value order from %s: %s - $%.2f%n", customerName, order.orderId(), order.totalAmount()); // Check if order needs special shipping if (order.totalAmount() > 5000) { System.out.println(" -> Requires premium shipping"); } } } Real-World Use Cases
7. Practical Application Examples
// API Response processing with pattern matching public class ApiResponseProcessor { public sealed interface ApiResponse<T> permits Success, Error, Loading, Empty { boolean isSuccess(); default boolean isError() { return !isSuccess(); } } public record Success<T>(T data, String message, int statusCode) implements ApiResponse<T> { @Override public boolean isSuccess() { return true; } } public record Error<T>(String errorCode, String message, Throwable cause) implements ApiResponse<T> { @Override public boolean isSuccess() { return false; } } public record Loading<T>(String progressMessage) implements ApiResponse<T> { @Override public boolean isSuccess() { return false; } } public record Empty<T>() implements ApiResponse<T> { @Override public boolean isSuccess() { return false; } } // Process API responses with pattern matching public static <T> void handleApiResponse(ApiResponse<T> response) { switch (response) { case Success<T> success -> { T data = success.data(); String message = success.message(); int statusCode = success.statusCode(); System.out.printf("Success (%d): %s%n", statusCode, message); processSuccessData(data); } case Error<T> error -> { String errorCode = error.errorCode(); String errorMessage = error.message(); Throwable cause = error.cause(); System.err.printf("Error %s: %s%n", errorCode, errorMessage); if (cause != null) { cause.printStackTrace(); } } case Loading<T> loading -> { String progress = loading.progressMessage(); System.out.println("Loading: " + progress); } case Empty<T> empty -> { System.out.println("No data available"); } } } private static <T> void processSuccessData(T data) { // Type-specific processing based on data type if (data instanceof List<?> list) { System.out.println("Received list with " + list.size() + " items"); } else if (data instanceof Map<?, ?> map) { System.out.println("Received map with " + map.size() + " entries"); } else if (data instanceof String str) { System.out.println("Received string: " + str); } else { System.out.println("Received data: " + data); } } // Process multiple API responses public static void processMultipleResponses(List<ApiResponse<?>> responses) { for (ApiResponse<?> response : responses) { if (response instanceof Success<?> success) { Object data = success.data(); System.out.println("Processing successful response with data: " + data); } else if (response instanceof Error<?> error) { System.err.println("Error encountered: " + error.message()); } } } } // Configuration processing with deconstruction public class ConfigurationProcessor { public record DatabaseConfig( String url, String username, String password, int poolSize, Map<String, String> properties ) { public DatabaseConfig { if (poolSize <= 0) { throw new IllegalArgumentException("Pool size must be positive"); } if (properties == null) { properties = new HashMap<>(); } } } public record ServerConfig( String host, int port, boolean sslEnabled, int maxConnections, List<String> allowedOrigins ) { public ServerConfig { if (port < 1 || port > 65535) { throw new IllegalArgumentException("Invalid port number"); } if (allowedOrigins == null) { allowedOrigins = new ArrayList<>(); } } } public record AppConfig( String name, String version, DatabaseConfig database, ServerConfig server, Map<String, Object> features ) { public AppConfig { if (features == null) { features = new HashMap<>(); } } } public static void validateAndProcessConfig(AppConfig config) { // Deconstruct configuration String appName = config.name(); String version = config.version(); DatabaseConfig dbConfig = config.database(); ServerConfig serverConfig = config.server(); Map<String, Object> features = config.features(); // Validate database configuration validateDatabaseConfig(dbConfig); // Validate server configuration validateServerConfig(serverConfig); // Process features processFeatures(features); System.out.printf("Configuration validated for %s v%s%n", appName, version); } private static void validateDatabaseConfig(DatabaseConfig dbConfig) { String url = dbConfig.url(); String username = dbConfig.username(); int poolSize = dbConfig.poolSize(); if (url == null || url.isBlank()) { throw new IllegalArgumentException("Database URL is required"); } if (username == null || username.isBlank()) { throw new IllegalArgumentException("Database username is required"); } if (poolSize > 100) { System.out.println("Warning: Large connection pool size: " + poolSize); } } private static void validateServerConfig(ServerConfig serverConfig) { String host = serverConfig.host(); int port = serverConfig.port(); boolean sslEnabled = serverConfig.sslEnabled(); if (host == null || host.isBlank()) { throw new IllegalArgumentException("Server host is required"); } if (sslEnabled && port == 80) { System.out.println("Warning: SSL enabled but using HTTP port 80"); } } private static void processFeatures(Map<String, Object> features) { for (Map.Entry<String, Object> entry : features.entrySet()) { String featureName = entry.getKey(); Object featureConfig = entry.getValue(); // Pattern matching on feature configuration type if (featureConfig instanceof Boolean enabled) { System.out.printf("Feature %s: %s%n", featureName, enabled ? "ENABLED" : "DISABLED"); } else if (featureConfig instanceof Map<?, ?> nestedConfig) { System.out.printf("Feature %s has nested configuration with %d settings%n", featureName, nestedConfig.size()); } else if (featureConfig instanceof List<?> list) { System.out.printf("Feature %s has list configuration with %d items%n", featureName, list.size()); } } } } This comprehensive guide covers Java's deconstruction patterns from basic record usage to advanced nested pattern matching, providing practical examples and real-world use cases for modern Java development.