SwadhyAI Notes

All Java notes

Java Packages and API

›Short versionOpen if you only have a minute.
  • A package is a namespace. The package line must match the directory, and the launcher uses the full name.
  • Import only shortens a name. It does not grant access. Private and package-private members stay hidden.
  • Types in the same package see package-private members. That is the boundary for helpers that are not API.
  • java.lang is imported for you. String and Object need no import line. Everything else does, or you write the full name.
  • The public types of a package are its API. The platform API is the same idea, at the scale of the JDK.
  • A static import brings a static field or method into the short-name space. Prefer a single member over a star.

Two classes both named Date can sit in one program, one from the calendar utilities and one from a database driver. The is the family name that keeps them apart. The is the short list of public types you actually expect other code to call.

The name and the folder

The first line of the file, before the import lines and the class, declares the package. The path from the classpath root repeats those segments.

com/bank/account/Account.java
package com.bank.account;

public class Account {
    private int balance;

    public int balance() {
        return balance;
    }
}

Compile from the directory that contains com, then run the . The class file lands in the same nested folders.

Terminal
$ javac com/bank/account/Account.java
$ java com.bank.account.Account

A file with no package line sits in the unnamed package. It cannot be imported by a named package. Give real code a package as soon as a second file needs to find it.

Import is a nickname

An lets another package use the short name. Access is unchanged. A public class can be imported. A package-private class cannot be named from outside, with or without an import.

com/bank/report/Statement.java
package com.bank.report;

import com.bank.account.Account;

public class Statement {
    private final Account account;

    public Statement(Account account) {
        this.account = account;
    }
}

types need no import. String is java.lang.String.List is not. It lives in java.util, so you import it or write the full name. When two imported short names would collide, keep one import and spell the other type out: java.sql.Date beside java.util.Date.

A is the same nickname for a static member.

java
import static java.lang.Math.PI;

double circumference(double radius) {
    return 2 * PI * radius;
}

What you publish

Callers in com.bank.report should depend on Account, not on the package-private class that rounds interest. That split is the API. The JDK works the same way: java.util.ArrayList is a public class you are invited to construct, and many cooperating types in that package are not part of the story you need.

Name packages after a stable owner and a purpose, in lowercase: com.example.bank.account. The name is a global namespace shared with every jar on the classpath. Two libraries that both declare com.util.Helper will fight at launch.

Account has no access keyword on the class, and it lives in com.bank.account. Can com.bank.report import it?

No. A class with no access keyword is package-private. com.bank.report is a different package, even though the name looks related. Subpackages are not "inside" for access. Mark Account public if other packages should import it, and keep the helpers package-private.