Encapsulation in Java β Private Fields and Getters/Setters
Encapsulation is the principle of hiding an object's state behind methods. Fields are declared private; state changes go through public (or package-private) methods that can validate, log, synchronise, or fire events. The class controls its invariants β callers can't break them by reaching in directly.
The classical pattern
public class Circle {
private double radius; // hidden
public double getRadius() { // controlled read
return radius;
}
public void setRadius(double radius) { // controlled write
if (radius < 0) throw new IllegalArgumentException("radius < 0");
this.radius = radius;
}
}
Immutability β often the best encapsulation
public final class Circle { // final β can't be subclassed
private final double radius; // final β can't be reassigned
public Circle(double radius) {
if (radius < 0) throw new IllegalArgumentException("radius < 0");
this.radius = radius;
}
public double radius() { return radius; } // no setter
}
Records β encapsulation by default (Java 14+)
public record Circle(double radius) {
public Circle { // compact constructor β validation
if (radius < 0) throw new IllegalArgumentException("radius < 0");
}
}
// Fields are private and final, accessor is radius(), equals/hashCode/toString free.
When getters/setters are not needed
A record replaces most "data carrier" classes. For internal-only types in a package, package-private fields are sometimes cleaner than getters β the boundary is the package, not the class.
Defensive copies for mutable fields
public class Order {
private final List<Item> items;
public Order(List<Item> items) {
this.items = List.copyOf(items); // immutable snapshot
}
public List<Item> items() {
return items; // already immutable
}
}
Common mistakes
- Public fields β bypasses every benefit of encapsulation.
- Setters without validation β just a verbose public field.
- Returning internal mutable state β
return this.items;lets callers corrupt it. Wrap inList.copyOforCollections.unmodifiableList. - Auto-generating setters for fields that shouldn't be set β most fields should be final. Only add a setter if the invariant allows mutation.
Related
Pillar: OOP in Java. Tool: JSON to POJO generates encapsulated classes (POJO / record / Lombok).