Java Style Guide¶
What's on this page
- Core content for this topic in the Inkorporated enterprise OS.
- Practical guidance, roles, or standards as applicable.
What this enables
- Consistent enterprise operations and decision-making.
- Shared language for humans and cyborg AI agents.
This document outlines the coding standards and best practices for Java development within this project. Adhering to these guidelines ensures code consistency, readability, and maintainability.
Table of Contents¶
- General Principles
- Code Layout
- Naming Conventions
- Documentation and Comments
- Declarations
- Imports
- Control Structures
- Object Oriented Programming
- Exception Handling
- Generics
- Lambdas and Streams
- Concurrency
- Logging
- Testing
- Modern Java Features
- Recommended Tools
General Principles¶
- Standard: Follow the Google Java Style Guide unless otherwise specified.
- Readability: Code is read much more often than it is written. Prioritize clarity over cleverness.
- Consistency: Be consistent with the existing codebase. If you edit a file, follow its style.
- Simplicity: Keep code simple and focused. Avoid over-engineering.
Code Layout¶
- Indentation: Use 2 spaces (consistent with Google Style) or 4 spaces. Choose one and be consistent across the project. (Default for this guide: 2 spaces). Do not use tabs.
- Line Length: Limit lines to 100 characters.
- Line Wrapping:
- Break before operators.
- Indent continuation lines by at least 4 spaces (or 2 indentation levels).
- Blank Lines:
- Use blank lines to separate logical groups of code within methods.
- Use one blank line between methods.
- Use one blank line between the class declaration and the first member.
- Whitespace:
- Separate keywords (
if,for,catch) from the opening parenthesis with a space. - Separate closing parenthesis from the opening brace with a space.
- Do not use space between method name and opening parenthesis.
- Surround binary operators with spaces.
- Separate keywords (
- Braces:
- Used for
if,else,for,do, andwhilestatements, even when the body is empty or contains only a single statement (K&R style). - Opening brace on the same line as the declaration.
- Closing brace on its own line.
- Used for
Naming Conventions¶
- Classes/Interfaces/Records:
UpperCamelCase(PascalCase). Nouns for classes, adjectives or nouns for interfaces. - Methods:
lowerCamelCase. Verbs or verb phrases. - Variables:
lowerCamelCase. Meaningful names. - Constants:
UPPER_SNAKE_CASE.static finalfields that are immutable. - Packages:
lowercase. No underscores.com.example.project. - Type Parameters: Single capital letter (e.g.,
T,E,K,V). - Test Classes: End with
Test(e.g.,UserServiceTest).
Documentation and Comments¶
- Javadoc: Required for all
publicandprotectedmembers (classes, methods, fields).- Use
@param,@return,@throwstags. - The first sentence should be a summary fragment.
- Use
- Implementation Comments: Use
//for implementation details. Avoid block comments/* ... */for code explanations. - Self-Documenting Code: Prefer meaningful variable and method names over comments.
- TODOs: Use
TODO(User):format.
/**
* Calculates the sum of two integers.
*
* @param a the first integer
* @param b the second integer
* @return the sum of a and b
*/
public int add(int a, int b) {
return a + b;
}
Declarations¶
- Modifiers: Order should be:
public/protected/private,abstract,static,final,transient,volatile,synchronized,native,strictfp. - Annotations: Place annotations on separate lines before the declaration.
- Variables: Declare variables where they are first needed, and initialize them immediately if possible. Avoid C-style array declarations (
String[] argsnotString args[]). - Long Literals: Use uppercase
Lsuffix for long literals (3000Lnot3000l).
Imports¶
- No Wildcards: Avoid wildcard imports (
import java.util.*;). Import each class explicitly. - Order:
- Static imports.
- Standard
java.*andjavax.*packages. - Third-party packages (e.g.,
org.apache.*,com.google.*). - Local application packages.
- Separation: Insert a blank line between each group.
Control Structures¶
- Switch: Use the enhanced
switchexpression (Java 14+) where appropriate. Always include adefaultcase unless covering all enum cases. - Loops: Prefer enhanced
forloops (for (Type item : items)) over index-based loops unless the index is needed. - Conditionals: Avoid "yoda conditions" (
if (CONSTANT.equals(variable))). While safe, standardvariable.equals(CONSTANT)is preferred if null-safe, or useObjects.equals(). - Nesting: Avoid deep nesting. Return early (Guard Clauses).
Object Oriented Programming¶
- Immutability: Prefer immutable objects. Use
finalfields and constructor injection. - Interfaces: Prefer coding to interfaces rather than implementations (e.g.,
List<String> list = new ArrayList<>();). - Constructors: Chain constructors using
this()if multiple constructors exist. - Overriding: Always use
@Overrideannotation when overriding methods. - Utility Classes: Should be
finaland have a private constructor. - Records: Use
record(Java 16+) for data carriers (DTOs).
Exception Handling¶
- Checked vs Unchecked: Prefer unchecked exceptions (
RuntimeException) for recoverable errors or programming errors. Use checked exceptions sparingly. - Catching: Catch specific exceptions. Never catch
ExceptionorThrowableunless absolutely necessary (e.g., at the top-level main loop). - Ignored Exceptions: Don't ignore exceptions. At least log them. If ignoring is intentional, comment why and name the variable
ignored. - Try-with-resources: Use try-with-resources for
AutoCloseableresources (streams, connections).
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Generics¶
- Raw Types: Never use raw types (e.g.,
Listinstead ofList<String>). - Inference: Use the diamond operator
<>when instantiating generics. - Wildcards: Use
? extends Tfor producers (read-only) and? super Tfor consumers (write-only) (PECS: Producer Extends, Consumer Super).
Lambdas and Streams¶
- Lambdas: Keep lambdas short (one-liners preferred). If complex, extract to a method and use a method reference.
- Streams: Use streams for collection processing pipelines.
- Break long stream chains onto multiple lines, one operation per line.
- Side Effects: Avoid side effects in stream operations (e.g., modifying external state within
maporfilter).
List<String> names = users.stream()
.filter(User::isActive)
.map(User::getName)
.sorted()
.collect(Collectors.toList());
Concurrency¶
- Threads: Avoid creating threads manually. Use
ExecutorServiceorCompletableFuture. - Synchronization: Prefer
java.util.concurrentclasses (AtomicInteger,ConcurrentHashMap,Locks) oversynchronizedblocks/methods. - Virtual Threads: Use virtual threads (Java 21+) for high-throughput I/O-bound tasks.
- Thread Safety: Document thread safety of classes (
@ThreadSafe,@NotThreadSafe).
Logging¶
- Framework: Use SLF4J as the facade (with Logback or Log4j2 as implementation).
- Levels:
ERROR(failures),WARN(potential issues),INFO(milestones),DEBUG(diagnostic),TRACE(fine-grained). - Format: Do not use string concatenation. Use placeholders.
- Good:
log.debug("Processing user: {}", userId); - Bad:
log.debug("Processing user: " + userId);
- Good:
Testing¶
- Framework: JUnit 5 (Jupiter).
- Assertions: AssertJ or Truth for fluent and readable assertions.
- Mocking: Mockito.
- Naming:
MethodName_StateUnderTest_ExpectedBehavior. - Structure: Tests should follow AAA (Arrange, Act, Assert).
@Test
void calculateTotal_WithValidItems_ReturnsSum() {
// Arrange
Order order = new Order(List.of(new Item(10), new Item(20)));
// Act
int total = order.calculateTotal();
// Assert
assertThat(total).isEqualTo(30);
}
Modern Java Features¶
- Records: Use for immutable data classes.
- Text Blocks: Use
"""for multi-line strings (SQL, JSON, HTML). - Pattern Matching: Use
instanceofwith pattern matching to avoid casting. - Switch Expressions: Use concise switch syntax.
- Sealed Classes: Use
sealedclasses to restrict inheritance hierarchies.
// Pattern Matching
if (obj instanceof String s) {
System.out.println(s.toLowerCase());
}
// Switch Expression
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
default -> 8;
};
Recommended Tools¶
- Build Systems: Maven or Gradle.
- Formatter:
google-java-formator Spotless. - Linter: Checkstyle, PMD, SonarLint.
- Static Analysis: SpotBugs (successor to FindBugs).
- Testing: JUnit 5, Mockito, AssertJ.
Related Interview Questions¶
- Practice Questions: Test your knowledge of Java concepts.