Encapsulation & Access Modifiers

Encapsulation means an object protects its own data: fields are hidden, and the outside world interacts only through methods that keep the object valid. If anyone could set an account's balance to any value, every rule about withdrawals would be meaningless. Access modifiers enforce the boundary.

The problem

JAVA
class Account {
    double balance;
}

public class Main {
    public static void main(String[] args) {
        Account acc = new Account();
        acc.balance = -1_000_000;
        System.out.println(acc.balance);
    }
}
Output
-1000000.0

Nothing stops other code from putting the object into an impossible state.

private fields, public methods

JAVA
class Account {
    private double balance;

    public double getBalance() {
        return balance;
    }

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

    public boolean withdraw(double amount) {
        if (amount <= 0 || amount > balance) {
            return false;
        }
        balance -= amount;
        return true;
    }
}

public class Main {
    public static void main(String[] args) {
        Account acc = new Account();
        acc.deposit(100);
        System.out.println(acc.withdraw(30));
        System.out.println(acc.withdraw(500));
        System.out.println(acc.getBalance());
    }
}
Output
true
false
70.0

Now the only way to change the balance is through deposit and withdraw, which enforce the rules. The class can later change how it stores the balance without breaking any code that uses it.

Access modifiers

ModifierVisible to
privateOnly the same class
(none) — "package-private"Classes in the same package
protectedSame package, plus subclasses (lesson 28)
publicEveryone
JAVA
class Secret {
    private String code = "1234";
}

class Spy {
    String steal(Secret s) {
        return s.code;
    }
}

public class Main {
    public static void main(String[] args) {
    }
}
Compiler error
Main.java:7: error: code has private access in Secret

A good default: make fields private, make methods public only if other classes need them, and keep helpers private.

Getters and setters

JAVA
class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        setName(name);
        setAge(age);
    }

    public String getName() { return name; }
    public int getAge() { return age; }

    public void setName(String name) {
        if (name == null || name.isBlank()) throw new IllegalArgumentException("Name required");
        this.name = name.strip();
    }

    public void setAge(int age) {
        if (age < 0 || age > 150) throw new IllegalArgumentException("Invalid age: " + age);
        this.age = age;
    }
}

public class Main {
    public static void main(String[] args) {
        Person p = new Person("  Ana ", 30);
        p.setAge(31);
        System.out.println("[" + p.getName() + "] " + p.getAge());
    }
}
Output
[Ana] 31

Getters (getX, or isX for booleans) and setters (setX) are the standard way to expose fields with control. Many frameworks rely on these names.

Don't add setters by reflex

A setter for every field isn't really encapsulation — it just makes the fields public with extra steps. Prefer methods that express intentions (deposit, ship, cancel) and immutable objects where possible. Ask: what operations does this object support, and what rules must always hold?

Returning internal collections

JAVA
import java.util.ArrayList;
import java.util.List;

class Playlist {
    private final List<String> songs = new ArrayList<>();

    public void add(String song) { songs.add(song); }

    public List<String> getSongs() {
        return List.copyOf(songs);
    }
}

public class Main {
    public static void main(String[] args) {
        Playlist p = new Playlist();
        p.add("Low Tide");
        try {
            p.getSongs().add("Hacked");
        } catch (UnsupportedOperationException e) {
            System.out.println("Can't modify the playlist from outside");
        }
        System.out.println(p.getSongs());
    }
}
Output
Can't modify the playlist from outside
[Low Tide]

Returning the internal list would let callers change it behind the object's back. Returning an unmodifiable copy keeps the object in charge. (Lists are covered in lesson 40.)

Try it yourself

Create a Thermostat whose target temperature can only be set between 10 and 30 degrees.

Try it yourself · Main.java
Edit the code, copy it into Main.java and run java Main.java (Java 25+). How to set up Java
Output
30.0
18.5