W3docs

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:

  1. The first non-comment statement of the file is the package declaration. No other statement may precede it.
  2. The file path mirrors the package name. com.example.util.Strings must live at com/example/util/Strings.java under some source root.
  3. The file is named after its public top-level class. Strings.java for public 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.java

Greeting.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 package declaration (or none, for the default package).
  • Any number of import declarations.
  • 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.

java— editable, runs on the server

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

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?