---
overlay: Java Specialization
parent_agent: Super Coder
description: "Java design patterns and enterprise development"
---

## JAVA-SPECIFIC GUIDELINES

You are working in a **Java** codebase. Apply these principles with zero exceptions.

### Exception Handling
- Use **checked exceptions** for recoverable conditions, **unchecked** for programming errors
- Create a base application exception: `AppException extends RuntimeException`
- Domain exceptions extend the base: `UserNotFoundException extends AppException`
- Never catch `Exception` or `Throwable` broadly — catch specific types
- Always include the original cause: `throw new AppException("context", originalException)`
- Use try-with-resources for all `AutoCloseable` resources — never manual `finally` for cleanup

### Immutability — Default to Final
- Make fields `final` by default — mutable only when mutation is required
- Use `Collections.unmodifiableList()` or `List.of()` for immutable collections
- Prefer **record types** (Java 16+) for data carriers: `record User(String name, String email) {}`
- Use builder pattern for objects with many optional fields

### Modern Java Patterns
- Use **Stream API** for collection processing — but keep pipelines short and readable
- Use `Optional<T>` for return types that may not have a value — never for parameters or fields
- Use `var` for local variables when the type is obvious from context
- Use **switch expressions** (Java 14+) with pattern matching when available
- Use **sealed classes** (Java 17+) for restricted type hierarchies
- Use **text blocks** (`"""`) for multi-line strings

### Annotations
- `@Override` on all overridden methods — non-negotiable
- `@Nullable` / `@NonNull` (from JSR-305 or JetBrains) on public API parameters and return types
- `@Deprecated(forRemoval = true)` with `@deprecated` Javadoc tag — never deprecate without replacement guidance
- Use Lombok sparingly — `@Getter`, `@Builder`, `@RequiredArgsConstructor` are fine; `@Data` hides mutation

### Package Conventions
- Follow the project's existing package structure — don't introduce new conventions
- Organize by feature, not by layer (unless the project already uses layers)
- One public class per file — file name matches class name
- Keep packages focused — if a package has >15 classes, it probably needs splitting

### Dependency Injection
- Use constructor injection — not field injection (`@Autowired` on fields is an anti-pattern)
- Prefer interface types in constructor parameters for testability
- Keep constructors focused — if >5 parameters, the class may have too many responsibilities

### Naming Conventions
- `PascalCase` for classes, interfaces, enums, records
- `camelCase` for methods, fields, parameters, local variables
- `UPPER_SNAKE_CASE` for constants (`static final`)
- Interfaces: no `I` prefix — `UserRepository` not `IUserRepository`
- Boolean methods: `is*`, `has*`, `can*`, `should*`

### Testing Considerations
- Write code with dependency injection for testability
- Prefer composition over inheritance — easier to mock
- Use `@VisibleForTesting` (Guava) to annotate package-private methods exposed for testing
