V
Vel·ToolKit
Simple · Fast · Ready to use
EN
Chapter 7 of 20

Packages & Access Control

package, the four access modifiers, import, JAR

Why Packages

A package is Java's namespace; its purposes: avoid same-name class collisions across libraries, organize the code hierarchy, and work with access modifiers for encapsulation. The first line of each .java file (if any) must be the package declaration, then imports, then classes.

// src/main/java/com/example/user/User.java
package com.example.user;

public class User {
    public String name;
}

Directory and Package-Name Constraints

Package naming convention: all lowercase, dot-separated layers, usually starting with the organization's reversed domain (e.g. com.example.myapp). **The directory structure must match the package name** — files of package com.example.user must live under com/example/user/.

src/main/java/
├── com/example/
│   ├── user/
│   │   ├── User.java        // package com.example.user;
│   │   └── UserService.java // package com.example.user;
│   └── order/
│       └── Order.java        // package com.example.order;
└── Main.java                  // default package (not recommended)

import and import static

import brings a class name from another package into the current file's scope so you can use the short name. Classes in the same package need no import. java.lang.* is "imported by default" — String / Math / System, etc., need no import.

// Greeter.java
package com.example.app;

import java.util.List;             // single-class import (recommended)
import java.util.ArrayList;
import java.util.*;                 // whole-package wildcard (generally discouraged, poor readability)

import static java.lang.Math.PI;    // static import: use PI directly instead of Math.PI
import static java.lang.Math.sqrt;

public class Greeter {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>(Arrays.asList("Alice", "Bob"));
        System.out.println(names);
        System.out.println(PI);
        System.out.println(sqrt(2));
    }
}

The Four Access Modifiers

Java controls member visibility with modifiers. From strict to loose: private < package-private (default) < protected < public.

Modifier      Class  Package  Subclass  Other pkg
--------      -----  -------  --------  ---------
private        ✓      ✗        ✗         ✗
(none)         ✓      ✓        ✗         ✗     ← package-private (default)
protected      ✓      ✓        ✓         ✗
public         ✓      ✓        ✓         ✓
// Visibility.java
package com.example.app;

public class Visibility {
    public    int pub   = 1;   // accessible to anyone
    protected int prot  = 2;   // same package + subclasses
              int pkg   = 3;   // same package (no modifier)
    private   int priv  = 4;   // only in this class

    public static void main(String[] args) {
        Visibility v = new Visibility();
        // all 4 are accessible within this class
        System.out.println(v.pub + " " + v.prot + " " + v.pkg + " " + v.priv);
    }
}

Top-Level Classes and the public class Rule

A .java file can contain multiple top-level classes, but **at most one** can be public, and the public class's name must exactly match the file name. Other non-public top-level classes can only be used within the same file.

// User.java   <-- the file must be named User.java
package com.example.app;

public class User {            // a public top-level class must match the file name
    String name;
}

class Helper {                  // a package-private helper class can coexist
    static String tag = "util";
}

JAR: Publish and Run

A JAR is essentially a ZIP archive containing .class files, resources, and a META-INF/MANIFEST.MF descriptor. The jar command packages it; java -jar runs it. Third-party libraries (downloaded from Maven Central) are just a bunch of JARs.

# assume the source is already javac-compiled into build/
$ jar cfe app.jar com.example.app.Main -C build .
# c = create, f = file name, e = entry-point main class

$ java -jar app.jar
Hello, World!

# inspect the jar contents
$ jar tf app.jar
META-INF/
META-INF/MANIFEST.MF
com/example/app/Main.class
...