Q: What is encapsulation? Why does it matter beyond "private fields + getters/setters"?
Answer:
Encapsulation = bundling state + behavior + hiding internal representation behind a stable interface. The point isn't "use private" — it's decouple callers from implementation so internals can change.
Naive "Encapsulation" (Anti-pattern)
class User {
private String name;
private List<Order> orders;
public String getName() { return name; }
public void setName(String n) { this.name = n; }
public List<Order> getOrders() { return orders; } // ❌ leaks mutable internal list
public void setOrders(List<Order> o) { this.orders = o; }
}
Caller can mutate getOrders().clear() — bypasses class. This is a public field with extra steps.
Real Encapsulation
public final class User {
private final String name;
private final List<Order> orders = new ArrayList<>();
public User(String name) { this.name = Objects.requireNonNull(name); }
public String name() { return name; }
public List<Order> orders() {
return Collections.unmodifiableList(orders); // defensive
}
public void placeOrder(Order o) { // behavior, not setter
if (orders.size() >= 100) throw new IllegalStateException("max orders");
orders.add(o);
}
}
Principles
- Hide state. Fields private; never expose mutable internals.
- Defensive copies for mutable inputs/outputs (or use immutable types).
- Validate at boundaries. Reject bad input in constructor/method.
- Behavior over setters.
placeOrder()notsetOrders()— captures invariants. - Minimal API. Only expose what callers need.
Why It Matters
- Refactor safely. Change
ordersfromListtoLinkedHashSetwithout breaking callers. - Invariants hold. "Max 100 orders" enforced — caller can't break it.
- Concurrency. Internal state can be made thread-safe in one place.
- Testability. Behavior methods describe domain rules; tests assert behavior, not field values.
Java 16+ Records
public record Money(BigDecimal amount, Currency currency) {
public Money {
Objects.requireNonNull(amount);
if (amount.signum() < 0) throw new IllegalArgumentException("negative");
}
}
Compact, immutable, validated. Fits encapsulation goals for value types.
Encapsulation vs Information Hiding
- Encapsulation: bundling state + behavior in one unit.
- Information hiding: design decisions hidden behind interfaces.
- Java's
privateenforces both. Modules (module-info.java, JPMS) extend it across packages.