In Java, package-info.java is a special source file used to document and annotate an entire package rather than individual classes. It does not define any classes or interfaces; instead, it holds Javadoc comments and package-level annotations tied to the package declaration.
Why Package-Level Documentation Matters
As projects grow, the number of classes and interfaces increases, and understanding their relationships becomes harder. Class-level Javadoc explains individual types but often fails to describe the “big picture” of how they fit together, which is where package-level documentation becomes valuable.
By centralizing high-level information in package-info.java, teams can describe the purpose of a package, its design rules, and how its types should be used without scattering that information across many files.
The Structure of package-info.java
A typical package-info.java file contains three elements in this order:
- A Javadoc comment block that describes the package.
- Optional annotations that apply to the package as a whole.
- The
packagedeclaration matching the directory structure.
This structure makes the file easy to scan: documentation at the top, then any global annotations, and finally the declaration that links it to the actual package.
A Comprehensive Example
Imagine an application with a com.example.billing package that handles invoicing, payments, and tax calculations. A rich package-info.java for that package could look like this:
/**
* Provides the core billing and invoicing functionality for the application.
*
* <p>This package defines:
* <ul>
* <li>Immutable value types representing invoices, line items, and monetary amounts.</li>
* <li>Services that calculate totals, apply discounts, and handle tax rules.</li>
* <li>Integration points for payment providers and accounting systems.</li>
* </ul>
*
* <h2>Design Guidelines</h2>
* <ul>
* <li>All monetary calculations use a fixed-precision type and a shared rounding strategy.</li>
* <li>Public APIs avoid exposing persistence details; repositories live in a separate package.</li>
* <li>Domain objects are designed to be side‑effect free; state changes go through services.</li>
* </ul>
*
* <h2>Thread Safety</h2>
* <p>Value types are intended to be thread‑safe. Service implementations are stateless or guarded
* by application-level configuration. Callers should not share mutable collections across threads.
*
* <h2>Usage</h2>
* <p>Client code typically starts with the {@code InvoiceService} to create and finalize
* invoices, then delegates payment processing to implementations of {@code PaymentGateway}.
*/
@javax.annotation.ParametersAreNonnullByDefault
package com.example.billing;
Note on the Annotation
The annotation @javax.annotation.ParametersAreNonnullByDefault used here is part of the JSR-305 specification, which defines standard Java annotations for software defect detection and nullability contracts. This particular annotation indicates that, by default, all method parameters in this package are considered non-null unless explicitly annotated otherwise.
Using JSR-305 annotations like this in package-info.java helps enforce global contract assumptions and allows static analysis tools (such as FindBugs or modern IDEs) to detect possible null-related errors more effectively.
Using Package-Level Annotations Effectively
Even without other annotations, package-info.java remains a powerful place to define global assumptions via annotations. Typical examples include nullness defaults from JSR-305, deprecation of an entire package, or framework-specific configuration.
By keeping only meaningful annotations, you avoid clutter while benefiting from centralized configuration.
When and How to Introduce package-info.java
The workflow for introducing package-info.java stays the same:
- Create
package-info.javainside the target package directory. - Write a clear Javadoc block that answers “what lives here” and “how it should be used.”
- Add only those package-level annotations that genuinely express a package-wide rule.
- Keep the file up to date whenever the package’s design or guarantees change.
With this approach, your package-info.java file becomes a concise, accurate source of truth about each package in your codebase, while clearly documenting the use of important annotations like those defined by JSR-305.
Leave a Reply