Encapsulation

OOP · lesson 3 of 43 · 3 min read

Why fields go private, and how keeping rules next to data stops callers from breaking your object.

Open this lesson in the learning hub

Key points

  • Make fields private. Expose behaviour, not data. Callers ask the object to do things instead of reaching inside.
  • The point is not secrecy. It is that the rules about the data live next to the data and cannot be skipped.
  • A getter and setter for every field is not encapsulation, it is a struct with extra steps. Expose only what is needed.
  • Public API is a promise you must keep. Private internals can be rewritten on a Tuesday and nobody notices.
  • Package-private (no modifier at all) is the quiet default: visible inside the package, invisible outside it.

Example

public class Main {
    static class Thermostat {
        private int celsius = 20;                 // nobody touches this directly

        public int celsius() { return celsius; }

        public void setCelsius(int value) {       // the rule lives with the data
            if (value < 5 || value > 30) {
                throw new IllegalArgumentException("out of range: " + value);
            }
            this.celsius = value;
        }

        public void warmer() { setCelsius(celsius + 1); }
    }

    public static void main(String[] args) {
        Thermostat t = new Thermostat();
        t.warmer();
        System.out.println("now " + t.celsius() + "C");

        try {
            t.setCelsius(99);
        } catch (IllegalArgumentException e) {
            System.out.println("blocked: " + e.getMessage());
        }
        System.out.println("still " + t.celsius() + "C - invariant held");
    }
}

Private data plus public behaviour means your invariants cannot be broken from outside.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the OOP course, and every lesson in it is listed on the OOP contents page.