1.1. File Naming:
* Extension: .java
.
* Name: Must match the public class/interface name, case-sensitive.
1.2. File Encoding:
* UTF-8
for all Java source files.
1.3. File Organization:
* One top-level public class or interface per .java
file.
* Multiple top-level classes/interfaces in one file discouraged (except private helpers or very closely related small classes); only one can be public.
1.4. Package and Imports:
1.4.1. Package Declaration:
* Mandatory for every source file (unless default package, which is strongly discouraged).
* First statement in the file.
1.4.2. Import Statements:
* Follow package declaration, precede class/interface definitions.
* Order:
1. static ...
(grouped)
2. java.*
3. javax.*
4. Other external libraries (e.g., org.*
, com.*
)
5. Internal project imports
* Alphabetical within each group.
* Avoid wildcard imports (e.g., java.util.*
), prefer specific imports. Exception: enum members or utility class static members if numerous are used.
* Do not import from java.lang
(e.g., String
, Integer
).
* Remove all unused imports.
2.1. General Principles:
* Names: Descriptive, self-explanatory. English.
* Abbreviations: Avoid unless widely understood (e.g., URL
, HTML
, AI
).
2.2. Packages:
* lowercase.only.concatenated
.
* Reversed domain name: com.example.project.module
.
* No underscores or hyphens.
* Example: com.yourdomain.ai.featureengineering
2.3. Classes and Interfaces:
* UpperCamelCase
(PascalCase).
* Nouns or noun phrases. Examples: NeuralNetworkClassifier
, DataProcessor
, PredictionResult
.
* Interfaces: May be adjectives (e.g., Runnable
) or noun-based like classes. I
prefix (e.g., IDataService
) permissible if project convention improves clarity.
* Abstract Classes: Describe the abstraction (e.g., Shape
). Avoid Abstract
prefix unless dictated by established patterns.
* Test Classes: Suffix with Test
(e.g., MyServiceTest
).
2.4. Methods:
* lowerCamelCase
.
* Verbs or verb phrases. Examples: trainModel()
, predict(features)
, calculateLoss()
.
* Getters: getX()
. For booleans: isX()
or hasX()
.
* Setters: setX(value)
.
* Boolean-returning methods: Sound like questions (e.g., isEmpty()
).
2.5. Variables:
2.5.1. Instance and Static Variables:
* lowerCamelCase
. Examples: customerName
, totalConnections
.
* No m
or s
prefixes unless strong project convention.
2.5.2. Local Variables:
* lowerCamelCase
. Examples: index
, userName
.
* Declare close to first use.
2.5.3. Parameters:
* lowerCamelCase
. Examples: message
, count
.
* Avoid single-letter names except for trivial cases (loop counters i,j,k
, coordinates x,y,z
, short lambdas).
2.6. Constants (static final fields):
* UPPER_SNAKE_CASE
. Examples: MAX_CONNECTIONS
, DEFAULT_TIMEOUT
.
* Declared static final
.
* For mutable objects, ensure true constancy or provide an unmodifiable view.
2.7. Enums:
* Type: UpperCamelCase
.
* Constants: UPPER_SNAKE_CASE
.
2.8. Type Parameters (Generics):
* Single uppercase letter (e.g., T
, E
, K
, V
).
* Descriptive UpperCamelCase
if it significantly improves readability for complex generics (e.g., RequestT
, InputType
).
3.1. Indentation: * 4 spaces. No tabs.
3.2. Line Length: * Maximum 100-120 characters. Wrap lines exceeding this.
3.3. Wrapping Lines: * Continuation line indent: Typically 8 spaces (two levels) or aligned with a higher-level expression. * Break before an operator. * Prefer higher-level breaks.
3.4. Braces:
* K&R style ("Egyptian brackets"):
* Opening brace {
: End of the line starting the construct.
* Closing brace }
: Own line, aligned with the start of the construct.
* Always use braces for if
, else
, for
, do
, while
blocks.
java // Example public class MyClass { public void myMethod(int arg) { if (arg > 0) { // code } else { // code } } }
3.5. Blank Lines (Vertical Whitespace): * One blank line: * Between methods. * Between local variables and first statement in a method. * Before block/single-line comments. * Between logical sections within a method. * Between field declarations. * Avoid multiple consecutive blank lines.
3.6. Horizontal Whitespace:
* Use a single space:
* Around binary operators (+
, =
, &&
).
* After commas in argument lists.
* After semicolons in for
statements.
* After colons in enhanced for
loops and ternary expressions.
* After keywords (if
, for
, while
, switch
, try
, catch
, finally
, synchronized
) followed by (
.
* Around ->
in lambdas.
* No spaces:
* Around unary operators (++x
, !condition
).
* Before semicolon or comma.
* Between method name and its opening parenthesis (
.
* After opening parenthesis (
or before closing parenthesis )
.
* Around dot .
operator.
* For type casts: after )
of cast and expression (e.g., (String)object
).
3.7. Parentheses: * Use liberally for clarity in complex expressions.
3.8. Annotations:
* On separate lines preceding the annotated element (unless very short in a parameter list).
* @Override
first, if present.
4.1. Javadoc Comments (/** ... */
):
* Mandatory for all public classes, interfaces, methods, and non-trivial public/protected fields.
* First sentence: Concise summary, ending with a period.
* Tags: Use @param
, @return
, @throws
, @see
, @since
, @deprecated
, @author
, @version
appropriately.
* @param <T> Description
for generic type parameters.
* @throws
: Document all checked exceptions and notable runtime exceptions.
4.2. Implementation Comments:
4.2.1. Block Comments (/* ... */
): For multi-line explanations of complex logic within methods.
4.2.2. Single-Line Comments (//
): For short explanations or end-of-line comments.
* Explain why, not just what (if code is self-explanatory).
* Avoid redundant comments.
* Keep comments updated.
* // TODO: Description
for pending tasks.
* // FIXME: Description
for known issues.
4.3. Class/Interface Comments:
* Javadoc: Describe purpose, responsibility, basic usage.
* Include @author
, @version
if project policy dictates.
* @since
for new public APIs.
5.1. Variable Declarations:
* One variable per line.
* Initialize locals where declared or as soon as value is known.
* Declare in narrowest possible scope.
* Use final
for variables not reassigned (locals, parameters, fields).
5.2. Array Declarations:
* int[] array
(not int array[]
).
5.3. Modifiers Order (common practice):
* public
/protected
/private
* abstract
* static
* final
* transient
* volatile
* default
(interface methods)
* synchronized
* native
* strictfp
* Example: public static final String MY_CONSTANT = "...";
5.4. Primitive Types vs. Boxed Types: * Prefer primitives (int, boolean) unless nullable type or generic argument is required.
5.5. Using var
(Java 10+):
* Use for local variables if it enhances readability (reduces boilerplate) and inferred type is clear.
* Do not use if it reduces clarity.
6.1. Simplicity: * Write simple, clear statements. Avoid overly complex statements.
6.2. for
Loops:
* Prefer enhanced for
loops (for-each
) for collections/arrays if index is not needed.
* for (Element element : elements)
6.3. switch
Statements:
* Always include default
case (even if just a comment or throws exception).
* Each case
usually ends with break
. Intentional fall-through must be commented (// fallthrough
).
* Use new switch
expressions (Java 14+) where appropriate.
6.4. try-catch-finally
Blocks:
* Use try-with-resources
for AutoCloseable
resources.
* Catch specific exceptions, not generic Exception
or Throwable
(unless necessary and handled properly).
* Do not ignore/swallow exceptions (empty catch block) without explicit, commented intent. Log or rethrow.
* finally
for cleanup code that must always execute.
6.5. return
Statements:
* Avoid complex expressions if they hinder readability; assign to a well-named local variable first.
* Multiple returns acceptable if they improve clarity and reduce nesting.
7.1. Magic Numbers/Strings: * Avoid. Use named constants.
7.2. String Concatenation:
* +
operator for simple cases.
* StringBuilder
, String.format()
, or String.join()
for complex/loop-based concatenations.
7.3. Ternary Operator (? :
):
* Use for simple conditional assignments. Avoid nesting.
7.4. Floating-Point Comparisons:
* Do not use ==
or !=
. Use a tolerance (epsilon) comparison.
7.5. Null Checks:
* Be mindful of NullPointerExceptions
.
* Use Objects.requireNonNull()
or explicit checks for critical parameters/variables.
* "constant".equals(variable)
to avoid NPE if variable
is null.
* Utilize Optional
(Java 8+) for methods that might not return a value.
8.1. Thread Safety:
* Ensure classes are thread-safe if intended for multi-threaded access.
* Prefer immutable objects (inherently thread-safe).
* Use appropriate synchronization ( synchronized
keyword, ReentrantLock
, java.util.concurrent
collections) for shared mutable state.
* Minimize scope of synchronized blocks. Avoid excessive synchronization.
8.2. Use java.util.concurrent
:
* Favor high-level utilities (ExecutorService
, ThreadPoolExecutor
, Future
, CompletableFuture
, concurrent collections) over low-level Thread.start()
, wait()
/notify()
.
8.3. volatile
:
* For variables accessed by multiple threads where visibility is critical and complex atomicity is not needed.
9.1. Premature Optimization: * Avoid. Write clear, correct code first. Profile and optimize bottlenecks if necessary.
9.2. Efficient Data Structures:
* Choose appropriate Java Collections based on use case (e.g., ArrayList
, LinkedList
, HashMap
).
9.3. String Manipulation:
* Use StringBuilder
for building strings in loops or complex scenarios due to string immutability.
9.4. I/O Operations:
* Use buffered I/O (e.g., BufferedReader
, BufferedInputStream
).
* Close resources promptly using try-with-resources
.
* Handle large datasets by streaming or chunking.
9.5. Lazy Initialization: * Use for expensive resources only when necessary; ensure thread-safety if applicable.
9.6. Algorithm Complexity: * Be aware of time and space complexity. Profile to identify bottlenecks.
9.7. Memory Management: * Avoid unnecessary object creation, especially in tight loops. * Be mindful of potential memory leaks.
10.1. Exceptions:
* Throw specific, appropriate exceptions. Create custom exceptions for application-specific errors.
* Do not use exceptions for normal control flow.
* Document thrown exceptions (@throws
in Javadoc).
* Wrap third-party exceptions in custom exceptions if beneficial for abstraction.
* Include context in exception messages.
10.2. Logging:
* Use a standard logging framework (SLF4J with Logback or Log4j2). Avoid System.out/err.println()
.
* Log at appropriate levels (DEBUG
, INFO
, WARN
, ERROR
).
* Provide meaningful log messages with context.
* Avoid logging sensitive information unless properly secured.
* Guard verbose logging (DEBUG
, TRACE
) with if (logger.isDebugEnabled())
if message construction is expensive.
11.1. Favor Immutability:
* Strive for immutable classes: final
fields, no setters, defensive copies of mutable fields, prevent extension (final
class or private constructors).
* Immutable objects are simpler, thread-safe, and freely sharable.
11.2. Collections:
* Use Collections.unmodifiable...()
or Java 9+ List.of()
, Set.of()
, Map.of()
for unmodifiable/immutable collections.
12.1. Clarity and Usability: * Design APIs easy to understand, use correctly, and hard to use incorrectly.
12.2. Encapsulation: * Hide internal details. Expose only what is necessary.
12.3. Consistency: * Maintain consistency in naming, parameter order, and behavior.
12.4. Use Interfaces: * Program to interfaces, not concrete implementations.
12.5. Avoid null
Returns:
* Prefer empty collections or Optional
for methods that might not find a result.
12.6. Validation:
* Validate input parameters for public APIs. Throw IllegalArgumentException
, NullPointerException
for invalid inputs.
13.1. Lambdas and Streams (Java 8+): * Use for functional interfaces and declarative collection processing. * Prioritize readability; refactor overly complex lambdas/streams.
13.2. Optional
(Java 8+):
* Use to represent potentially absent return values.
* Avoid as field types or method parameters without strong justification.
* Prefer orElse()
, orElseGet()
, orElseThrow()
over isPresent()
+ get()
.
13.3. Records (Java 14+): * Use for simple immutable data carrier classes.
13.4. Pattern Matching for instanceof
(Java 16+):
* Use to reduce boilerplate and improve type safety.
13.5. Sealed Classes (Java 17+): * Use to control inheritance hierarchies.
14.1. Unit Tests: * Mandatory for critical components and business logic. Aim for high coverage. * Frameworks: JUnit, TestNG. * Small, fast, independent tests. Arrange-Act-Assert (AAA) pattern. * Test edge cases, boundary conditions, null inputs, expected failures.
14.2. Integration Tests: * Verify interactions between different components/modules, databases, or external APIs. * Crucial for AI pipelines.
14.3. Model Evaluation Tests (AI-Specific): * Evaluate model performance metrics (accuracy, precision, recall, F1, RMSE, etc.) on validation/test datasets. * Include tests for known inputs/outputs to catch regressions. * Consider tests for fairness, bias, and robustness.
14.4. Testability: * Design code to be testable (e.g., use dependency injection, avoid hard-to-mock static calls for business logic).
14.5. Test Naming:
* Clearly indicate what is being tested (e.g., testCalculateScore_emptyInput_throwsException()
).
15.1. Input Validation: * Validate and sanitize all external inputs to prevent injection attacks.
15.2. Dependency Management: * Keep dependencies updated. Scan for known vulnerabilities (e.g., OWASP Dependency-Check).
15.3. Sensitive Data: * No hardcoded secrets (passwords, API keys). Use secure configuration or environment variables. * Handle sensitive data with care (logging, transmission).
15.4. Serialization/Deserialization:
* Be cautious with Java serialization. Consider alternatives (JSON, Protobuf). If used, implement readObject
carefully, use whitelists.
15.5. Principle of Least Privilege: * Application should run with minimum necessary permissions.
16.1. Data Handling for AI Models: * Efficient and correct handling of large datasets for preprocessing/feature engineering. * Mind memory usage and processing time for data transformations. * Prefer immutable objects for data points/features. * Encapsulate data cleaning, transformation, normalization logic. Ensure reproducibility. * Validate data quality, consistency, and expected formats early.
16.2. Model Representation: * Clearly define classes for model parameters, configurations, learned weights. * Consider dedicated numerical computation libraries (e.g., DL4J's ND4J, Tribuo) for efficiency.
16.3. Model Serialization/Deserialization (AI Models): * Robust mechanisms for saving/loading trained models (Java serialization, JSON, PMML, ONNX, framework-specific secure formats). * Ensure version compatibility if model formats evolve.
16.4. Algorithmic Clarity: * Strive for clarity reflecting underlying mathematical/logical steps. * Comment complex algorithmic parts, assumptions, trade-offs. * Where possible, leverage well-tested AI/ML library implementations (Deeplearning4j, Weka, Tribuo, Spark MLlib).
16.5. Resource Management for Training/Inference: * Proper management of resources (GPU memory - if applicable, large native memory buffers).
16.6. Reproducibility (AI/ML): * Ensure reproducibility: version code, data, control random seeds, deterministic operations where possible.
16.7. API Design for AI Services: * Clear, well-documented, versioned API endpoints if exposing models. * Consider asynchronous processing for long-running inference. * Define clear request/response schemas.
16.8. Modularity and Reusability (AI Components): * Design data loaders, preprocessors, models, evaluators as independent modules with well-defined interfaces.
16.9. Configuration Management (AI): * Externalize hyperparameters, model configurations, pipeline settings (e.g., properties, YAML, JSON).
17.1. Self-Correction/Refinement: * AI model should aim to review generated code against these rules and refine it.
17.2. Adaptability: * These rules may evolve; AI should be designed to adapt to updated standards.
18.1. DRY (Don't Repeat Yourself): * Avoid duplicate code. Encapsulate common logic.
18.2. KISS (Keep It Simple, Stupid): * Prefer simpler, clear solutions over overly complex ones.
18.3. YAGNI (You Aren't Gonna Need It): * Do not implement features not currently required.
18.4. SOLID Principles: * Single Responsibility Principle: A class has one reason to change. * Open/Closed Principle: Open for extension, closed for modification. * Liskov Substitution Principle: Subtypes substitutable for their base types. * Interface Segregation Principle: Clients not forced to depend on interfaces they don't use. * Dependency Inversion Principle: Depend on abstractions, not concretions.
18.5. Composition over Inheritance: * Favor composition for flexibility and to avoid tight coupling.