Java: Package Tutorial

By Xah Lee. Date: . Last updated: .

In Java, code can be organized into files, each file is a public class, and classes can be organized into packages, that's a directory of class files. A directory of class files is called “package”. This page show how it works.

How Java Package Works, Summary

Code can be organized into class files.

  1. One public class per file.
  2. The class name and file name must be the same. (For example, if a file is named “Abc.java”, then it must contain a public class named “Abc”.)

A set of class files can be placed into a directory, to form a package.

  1. To create a “package”, put class files in a directory, and each file must declare package dirName;
  2. package directory can be nested. That is, class files are placed in nested directories, and each class file must declare its dir paths, separated by dot, like this package dir1.dir2;.

Here's how to reference/import a class in a file or package.

  1. The main program can refer to classes in a directory by full name, like this: dirName.className. The dirName is relative to the main's file dir.
  2. The import keyword is used to avoid typing long reference names to classes. For example: import food.Cheese;, then you can new Cheese. To import all classes in a dir, use asterisk. Example: import food.*;
  3. Java import classes, not packages. The syntax import food.* imports all classes under food dir, but does not import classes in subdirectories of food dir, and import food.*.* is illegal syntax.

The rest of this page are details.

One Public Class Per File

In Java, you can put each class definition in a file.

// Save this in a file named Cheese.java

class Cheese {
    Cheese () {
        System.out.println("say Cheese.");
    }
}
// Save this in a file named RunMe.java, in the same dir as Cheese.java

class RunMe {
    public static void main(String[] args) {
        Cheese c = new Cheese();
        System.out.println("Cheese called!");
    }
}

Now, compile it javac RunMe.java and run it java RunMe. As you can see, RunMe is a program that calls the class Cheese in another file. In this way, you can have different files holding different classes, and calling these classes from a main file.

If there are more than one class definition in a file, only the one with the file name is available for other program to use. Other classes in the file can not be called by code outside of the file.

For example try change the Cheese.java to the following:

class Cheese {
    Cheese () {System.out.println("say Cheese.");}
    Chicken c = new Chicken();
}

class Chicken {
    Chicken () {System.out.println("say Chicken.");}
}

Now compile and run “RunMe” again. It all still work. Now both Cheese and Chicken are considered your subroutine tucked away neatly in a file. “Cheese” is the main one, identified by the file's name, while “Chicken” is a helper, not to be used outside of Cheese.java.

Now, try to put public in front of Chicken and see what happens. You'll see that it's a compiler error, because java does not allow a file to have more than 1 class to be visible outside the file. (and the one class visible outside must be the one having same name as the file.)

Try also private or protected in front of Cheese. 〔➤see Java's Access Specifiers

Package = Set of Classes in a Directory

You can organize class files into directories. For example, you can have a directory named “sound” that contain all classes that deals with sound, and another directory named “images” that contains all classes that deals with pictures, of your video game program.

// save me as StartMe.java

class StartMe {
    public static void main(String[] args) {
        pacman.Ladybug lb = new pacman.Ladybug();
        System.out.println("StartMe done");
    }
}

Now, create a directory there named “pacman”. Then, save the following code there as Ladybug.java.

// save me as Ladybug.java in a directory pacman

package pacman;

public class Ladybug {
    public Ladybug () {
        System.out.println("Ladybug initialize!");
    }
}

Now, compile StartMe.java and run it. As you can see, the class StartMe calls the Ladybug class under the pacman dir by this full reference: pacman.Ladybug. This is how Java calls classes in another directory.

Also, note that the Ladybug.java file starts with the line package pacman;. If you put a file into a directory as part of a package, that file needs to start with the line package dirName; (otherwise, that file won't be part of your package).

Also, note that the two public keywords in Ladybug needs to be there. Otherwise it won't compile. (try to experiment by changing the access specifier and compile.) 〔➤see Java's Access Specifiers

Package Nested Subdirectories

A package can have more than 1 level of sub-directories.

Suppose you have a collection of codes related to sound in a video game program. You put them under a “sound” directory. Now, some of these are related to processing sounds, while others are playing sounds. So, you can create subdirectories “process” and “play” as nested packages, to further organize your code.

Using our previous example, in the “pacman” dir create a directory “maze”, and in the “maze” dir create a file Labyrinth.java with the following code:

// save me as Labyrinth.java in directory pacman/maze

package pacman.maze; // this is dir structure!

public class Labyrinth {
    public Labyrinth () {
        System.out.println("i trap Minotaur!");
    }
}

And add a line to StartMe.java to call “Labyrinth”:

class StartMe {
    public static void main(String[] args) {
        pacman.Ladybug lb = new pacman.Ladybug();
        pacman.maze.Labyrinth rring = new pacman.maze.Labyrinth();
        System.out.println("StartMe done");
    }
}

So now we have these files and directory structure:

StartMe.java
pacman/
◆Ladybug.java
◆maze/
◆◆Labyrinth.java

Now compile and run StartMe.

Use 「import」 to Import a Class

To refer to a class in a package, you can:

import pacman.maze.Labyrinth; // import the class Labyrinth, under dir pacman/maze

class StartMe {
    public static void main(String[] args) {

        pacman.Ladybug lb = new pacman.Ladybug();

        Labyrinth rring = new Labyrinth(); // short, because we imported Labyrinth

        System.out.println("StartMe done");
    }
}

Import Many Classes: *

If you have many classes under a dir, you import them all with asterisk as wildcard, like this:

import pacman.*

Java import classes, not packages. For example, import pacman.* does not import classes in “pacman.maze”, and import pacman.*.* is illegal syntax.

Interfaces in a Package

Java interfaces can also be put into a package, just like classes. Like classes, it should be one interface per file.

〔➤see What's Interface in Java?

Default Package

If the file didn't declare a package, it is then in a “default package”, which is a package without name.

Pack Packages into Jar Archive

A package (a directory of classes) can be packages into a jar archive, one single file. Jar file is the standard way to distribute Java libraries and applications.

Java: Working with Jar File