Java Best Practices (17+)
Code Style
| Rule | Guideline | |------|-----------| | Formatter | google-java-format | | Analysis | SpotBugs, Error Prone | | Naming | Clear, no abbreviations |
Modern Features
| Feature | Usage | |---------|-------| | Records | Immutable data carriers | | Sealed classes | Restricted hierarchies | | Pattern matching | instanceof with binding | | var | Local type inference |
public record User(String id, String name) {}
if (obj instanceof String s && !s.isEmpty()) { process(s); }
public sealed interface Result<T> permits Success, Failure {}
record Success<T>(T value) implements Result<T> {}
record Failure<T>(Exception error) implements Result<T> {}
Error Handling
| Rule | Guideline | |------|-----------| | Specific exceptions | Not bare Exception | | Try-with-resources | For AutoCloseable |
try (var reader = new BufferedReader(new FileReader(path))) {
return reader.lines().toList();
} catch (IOException e) {
throw new ConfigException("Failed: " + path, e);
}
Project Structure
src/main/java/com/example/{domain,service}/
src/test/java/
pom.xml or build.gradle
Common Patterns
| Pattern | Usage | |---------|-------| | Optional | Null-safe returns | | Stream API | Functional collections | | Builder | Complex construction |
public Optional<User> findById(String id) {
return Optional.ofNullable(users.get(id));
}
Anti-Patterns
| Avoid | Use Instead | |-------|-------------| | Returning null | Optional<T> | | Mutable data | Records | | instanceof chains | Pattern matching |
Testing (JUnit 5 + AssertJ)
@Test void shouldProcess() {
var service = new Service(mockRepo);
var result = service.process(input);
assertThat(result.status()).isEqualTo(SUCCESS);
}