Encapsulation and Access Modifiers (Java)

Context: FIT2099_MOC · control who can see a method · the mechanism behind information hiding and loose coupling Parent Framework: OOP Building Blocks (Class, Object, Field, Method)

Quick Revision

  • 🎯 Objective: hide internal state behind private fields and expose only a deliberate public interface ➔ encapsulation / information hiding.
  • 📦 Core Components: public (world) | protected (package + subclasses) | default (package) | private (this class only).
  • ⚡ Key Constraint: encapsulation ≠ “getter + setter for everything” — expose only the accessors a client genuinely needs; a write-only or read-only field is often correct.

📝 How It Works

1. Encapsulation

  • Private fields ➔ mark data private so no outside class can read/write it directly.
  • Selective accessors ➔ add a getter and/or setter only where needed — not always both (a field may be read-only).
  • Why ➔ the class controls its own invariants (a setter can validate); internals can change without breaking clients.

2. Encapsulation Boundaries & ReD

  • Boundary ➔ anything visibility can be restricted across — the class, the package, the module (Java 9+), even a {} block scope.
  • Crossing = coupling ➔ any access to a member outside its own class/package crosses a boundary; each crossing is a dependency.
  • ReD (Reducing Dependency) ➔ expose (make public) only what client code truly needs and hide everything else, so there are fewer boundary crossings to break later.
  • Abstraction layer = the public interface ➔ the publicly-accessible face of a class/package/subsystem; size it so API complexity doesn’t exceed the benefit to clients (a car’s start/stop button, not an Airbus cockpit).
  • Connascence ➔ hidden coupling where changing one element forces a change in another; a well-encapsulated class validates its own state rather than relying on client code, reducing connascence. Leaking a mutable field breaks this — see Defensive Copying (Java).

3. The Four Access Levels (widest → narrowest)

ModifierClassPackageSubclassesWorld
public
protected
default (none)
private
  • public ➔ callable from anywhere; use for the intended interface.
  • protected ➔ visible in the same package and to subclasses — “pretty much package public”.
  • default (package-private) ➔ no keyword ➔ visible only within the same package.
  • private ➔ visible only inside the declaring class; the default for fields.

⚠️ Common Mistakes

  • 💡 protected on attributes ➔ discouraged (esp. fields) — it leaks state to every subclass and the whole package, weakening encapsulation; prefer private + a protected/public accessor.
  • 💡 Reflex getters+setters ➔ auto-generating both for every field re-exposes the state you just hid; add an accessor only when a client needs it.
  • 💡 default ≠ public ➔ omitting a modifier is package-private, not public — a subtle source of “why can’t another package see it?“.

🧠 Active Recall