Keep fields private and expose behaviour through methods, so the class alone guarantees that its state is always valid.
Why it matters
Getters, setters and validation
public class Main {
public static void main(String[] args) {
Account acc = new Account("Asha", 1000);
acc.withdraw(300);
System.out.println(acc.getOwner() + ": " + acc.getBalance());
try {
acc.withdraw(5000);
} catch (IllegalArgumentException e) {
System.out.println("rejected: " + e.getMessage());
}
System.out.println("balance still " + acc.getBalance());
}
}
class Account {
private final String owner;
private long balance; // hidden: no one can set it to -1
Account(String owner, long opening) {
if (owner == null || owner.isBlank()) throw new IllegalArgumentException("owner required");
this.owner = owner;
this.balance = opening;
}
String getOwner() { return owner; }
long getBalance() { return balance; } // read-only: no setBalance()
void withdraw(long amount) {
if (amount <= 0 || amount > balance)
throw new IllegalArgumentException("invalid amount " + amount);
balance -= amount;
}
}Asha: 700
rejected: invalid amount 5000
balance still 700Leaking mutable state — and defensive copies
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> input = new ArrayList<>(List.of("math", "physics"));
Leaky leaky = new Leaky(input);
Safe safe = new Safe(input);
input.add("hacked"); // caller mutates its own list
leaky.getSubjects().clear(); // caller mutates via the getter
System.out.println("leaky: " + leaky.getSubjects());
System.out.println("safe: " + safe.getSubjects());
try {
safe.getSubjects().add("x");
} catch (UnsupportedOperationException e) {
System.out.println("safe getter is read-only");
}
}
}
class Leaky {
private final List<String> subjects;
Leaky(List<String> subjects) { this.subjects = subjects; } // stores caller's list
List<String> getSubjects() { return subjects; } // hands out internals
}
class Safe {
private final List<String> subjects;
Safe(List<String> subjects) { this.subjects = List.copyOf(subjects); } // copy in
List<String> getSubjects() { return subjects; } // already unmodifiable
}leaky: []
safe: [math, physics]
safe getter is read-onlyEncapsulation vs abstraction
| Encapsulation | Abstraction | |
|---|---|---|
| Focus | How data is protected | What is exposed |
| Mechanism | private fields, accessors, validation | Interfaces, abstract classes, simple method names |
| Level | Implementation | Design |
How do you achieve encapsulation in Java?
Is a class with private fields and public getters/setters for all of them encapsulated?
What is a JavaBean?