---
description: Modern Java Language Features
alwaysApply: false
---

# Modern Java Language Features

Java 21+ features used deliberately to make code clearer.

## Records

```java
public record Money(BigDecimal amount, Currency currency) {
    public Money {
        if (amount.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Negative");
        Objects.requireNonNull(currency);
    }
}
```

Don't use records for: JPA entities, Spring beans, complex behavior classes.

## Sealed Classes

```java
public sealed interface PaymentResult permits PaymentSuccess, PaymentFailure {}
public record PaymentSuccess(String txId) implements PaymentResult {}
public record PaymentFailure(String msg) implements PaymentResult {}

return switch (result) {
    case PaymentSuccess s -> "Paid: " + s.txId();
    case PaymentFailure f -> "Failed: " + f.msg();
};
```

## Pattern Matching

```java
return switch (value) {
    case Integer i when i < 0 -> "negative";
    case String s when s.isEmpty() -> "empty";
    case null -> "null";
    default -> value.getClass().getSimpleName();
};
```

## Optional

```java
public Optional<User> findByEmail(String email) { ... }
return findByEmail(e).map(User::displayName).orElse("Unknown");
// Never: Optional.get() without check, Optional as field/parameter
```

## Collections

```java
var users = List.of("Alice", "Bob");         // Immutable
var copy = List.copyOf(mutableList);          // Defensive copy
var names = stream.map(User::name).toList();  // Unmodifiable (16+)
```

## Virtual Threads

```java
try (var exec = Executors.newVirtualThreadPerTaskExecutor()) { ... }
// Don't pool. Use ReentrantLock not synchronized. spring.threads.virtual.enabled=true
```

## Anti-Patterns

- **Never** raw types: `List list` → `List<User>`
- **Never** mutable public fields → records or private fields with getters
- **Never** return `null` for "not found" → `Optional` or `NotFoundException`
