Memra

Access control & packages

◈ 5 cards

public/protected/private/package access, the package/import library unit, and the silent default.

The library unit: a package

A package is Java's unit of reuse and namespacing. The package statement is the first non-comment line of a source file and maps directly to a directory path: a class declared package com.greenhouse.events; must live in com/greenhouse/events/. Other code pulls it in with import com.greenhouse.events.Event; (one type) or import com.greenhouse.events.*; (all public types of that package, not sub-packages). Without an import you must use the fully-qualified name com.greenhouse.events.Event.

The four access levels

Java has four access levels for members (fields, methods, constructors), ordered most-open to most-closed:

  • public — any code anywhere can access it. It is the deliberate, published interface of your class.
  • protected — the same package and subclasses (even in other packages). It says "this is for people extending me."
  • package-private (the default — no keyword) — only code in the same package. This is the level you get when you forget to write a modifier.
  • private — only the enclosing class itself. The implementation detail nobody outside touches.

A top-level class itself may be only public or package-private (default). There is no private or protected top-level class.

Worked example: a two-class package with mixed access

package bank;

public class Account {
    private double balance;          // hidden from everyone
    protected String owner;          // visible to subclasses + package
    double feeRate = 0.01;           // package-private (default)

    public void deposit(double amt) { balance += amt; }
    public double getBalance() { return balance; }
}
package bank;                        // SAME package as Account

class Auditor {
    void check(Account a) {
        System.out.println(a.getBalance());  // OK: public
        System.out.println(a.feeRate);       // OK: same package sees default
        // System.out.println(a.balance);    // COMPILE ERROR: private
    }
}

Auditor reaches feeRate only because it shares the bank package. Move Auditor to another package and that line stops compiling — but getBalance() keeps working because it is public. The rule of thumb: expose as little as possible. Make fields private and reach them through methods so you can change the internals later without breaking callers.

calling codeprivatedefaultprotectedpublicsame classyesyesyesyessame packagenoyesyesyessubclass,other pkgnonoyesyesanywhere elsenononoyesThe "default" column is what you get by writing no modifier at all.
Read a column downward to see how far a level reaches. Each column is a superset of the one to its left, which is why protected is strictly more open than the default.
NORMAL ~/memra/learn/comp-308/access-control-and-packages utf-8 LF