Skip to content

6 · 32 · 5 min

Encapsulation, and the getter that leaks

Encapsulation is hiding how something works so it can be changed without breaking anyone.

java
class Account {
    private double balance;

    public double getBalance() { return balance; }

    public void deposit(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("must be positive");
        balance += amount;
    }
}

balance is private, so nothing outside can set it directly, and the deposit rule cannot be bypassed. Change the internal representation to paise stored as a long, and no caller notices.

The leak

java
class Student {
    private List<String> courses = new ArrayList<>();
    public List<String> getCourses() { return courses; }
}

student.getCourses().add("hacked");     // this works

The field is private and there is no setter. It still worked.

private stops you reassigning the field. It says nothing about the object the field points at, and the getter handed out a reference to it. The caller is now mutating the student's own list.

Two fixes:

java
return new ArrayList<>(courses);              // a copy
return Collections.unmodifiableList(courses); // a read-only view

Why it matters more than it looks

Encapsulation is what makes a class changeable. A field nobody outside can touch can be renamed, retyped or removed this afternoon. A field everyone reaches into is frozen forever.