rules/java/coding-style.md
This file extends common/coding-style.md with Java-specific content.
record for value types (Java 16+)final by default — use mutable state only when requiredList.copyOf(), Map.copyOf(), Set.copyOf()// GOOD — immutable value type
public record OrderSummary(Long id, String customerName, BigDecimal total) {}
// GOOD — final fields, no setters
public class Order {
private final Long id;
private final List<LineItem> items;
public List<LineItem> getItems() {
return List.copyOf(items);
}
}
Follow standard Java conventions:
PascalCase for classes, interfaces, records, enumscamelCase for methods, fields, parameters, local variablesSCREAMING_SNAKE_CASE for static final constantscom.example.app.service)Use modern language features where they improve clarity:
instanceof — no explicit cast (Java 16+)// Pattern matching instanceof
if (shape instanceof Circle c) {
return Math.PI * c.radius() * c.radius();
}
// Sealed type hierarchy
public sealed interface PaymentMethod permits CreditCard, BankTransfer, Wallet {}
// Switch expression
String label = switch (status) {
case ACTIVE -> "Active";
case SUSPENDED -> "Suspended";
case CLOSED -> "Closed";
};
Optional<T> from finder methods that may have no resultmap(), flatMap(), orElseThrow() — never call get() without isPresent()Optional as a field type or method parameter// GOOD
return repository.findById(id)
.map(ResponseDto::from)
.orElseThrow(() -> new OrderNotFoundException(id));
// BAD — Optional as parameter
public void process(Optional<String> name) {}
RuntimeExceptioncatch (Exception e) unless at top-level handlerspublic class OrderNotFoundException extends RuntimeException {
public OrderNotFoundException(Long id) {
super("Order not found: id=" + id);
}
}
.map(Order::getTotal)See skill: java-coding-standards for full coding standards with examples.
See skill: jpa-patterns for JPA/Hibernate entity design patterns.