Creating Custom Packages in Java
Create your own Java packages — directory layout, package declaration, and how to compile and use them.
Reading other people's packages is one thing. Creating your own takes three small steps: pick a name, lay out the directory, and put the right package declaration at the top of each file. The compiler and JVM agree on a strict convention, and once you've done it twice it becomes muscle memory.
The three rules
Anything you write inside a package has to obey exactly three rules:
- The first non-comment statement of the file is the
packagedeclaration. No other statement may precede it. - The file path mirrors the package name.
com.example.util.Stringsmust live atcom/example/util/Strings.javaunder some source root. - The file is named after its public top-level class.
Strings.javaforpublic class Strings.
That's all there is. Everything else is convention.
A minimal example
Suppose you want a tiny utility package called com.w3docs.greet. Here's the layout:
project/
└── src/
└── com/
└── w3docs/
└── greet/
├── Greeter.java
├── Greeting.java
└── Main.javaGreeting.java:
package com.w3docs.greet;
public record Greeting(String language, String text) {}Greeter.java:
package com.w3docs.greet;
public class Greeter {
public Greeting greet(String name) {
return new Greeting("en", "Hello, " + name + "!");
}
}Main.java:
package com.w3docs.greet;
public class Main {
public static void main(String[] args) {
System.out.println(new Greeter().greet("Ada").text());
}
}All three files start with the same package com.w3docs.greet; line. Because they share a package, Greeter and Main can use Greeting with no import.
Compiling and running from the command line
From the project/ root, the canonical commands are:
# Compile every .java file under src/ into a parallel tree under out/
javac -d out $(find src -name "*.java")
# Run a main class by its fully-qualified name, telling the JVM where out/ is.
java -cp out com.w3docs.greet.Main-d out tells javac where to put the compiled .class files; it preserves the package directory structure. -cp out (classpath) is how java finds them at runtime — the next chapter on the Java classpath goes into the details.
If the package declaration doesn't match the file's location relative to the source root, javac accepts it (the package is what's declared, not what's inferred from the path) — but java will fail at runtime with NoClassDefFoundError. Always keep the two in sync.
Sub-packages aren't nested
It's tempting to think com.example "contains" com.example.util, but to the Java compiler they're two unrelated packages that happen to share a name prefix. A class in com.example has no special access to com.example.util's package-private members. There is no package inheritance.
What sub-packages do give you is a directory tree that's easy to navigate and a logical place to group related code. Most real projects use sub-packages by feature (auth, billing, parser) or by layer (controller, service, repository) — but neither choice gives the sub-package any extra access.
Compilation units and package-info.java
A .java file is also called a compilation unit, and it can contain:
- One
packagedeclaration (or none, for the default package). - Any number of
importdeclarations. - Any number of type declarations, of which at most one may be
public, and that one must match the file name.
There's also a special file named package-info.java whose only job is to carry package-level Javadoc and annotations:
/**
* Greeting utilities for the W3Docs Java book.
*/
@NullMarked
package com.w3docs.greet;No types — just the comment, optional annotations, and the package line. You'll see this in well-documented libraries.
A worked example
This program declares two types that would live in the same package in a real project and uses them together. The runnable widget here flattens the file structure so you can see the wiring in a single source listing, but in a real project each public type would live in its own .java file under the directory layout shown above.
What's next
Custom packages cover the code you write yourself. Most of the time, though, you'll lean on the JDK's packages — the standard library classes for collections, I/O, time, and so on. The next chapter is a guided tour of the ones you'll touch most often. Continue to Java built-in packages.
Practice
A Java source file declares `package com.example.util;` but is compiled and then run from a `.class` located at `out/com/example/Strings.class`. What happens?