Encapsulation keeps an object’s representation behind operations that preserve its rules.
Java encapsulation and object ownership
Working model
Private fields alone do not protect a mutable collection. If a getter returns the internal list, callers can alter it without using your methods. Return a snapshot when that behavior is unwanted.
Code
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AuditBatch {
private final List<String> eventIds = new ArrayList<>();
public void record(String eventId) {
if (eventId == null) throw new IllegalArgumentException("eventId");
eventIds.add(eventId);
}
public List<String> snapshot() {
return Collections.unmodifiableList(new ArrayList<>(eventIds));
}
}Copying takes O(n) time and O(n) space. The returned list cannot be modified through its own methods, and later additions to eventIds do not appear in the copy.
Cost and design choices
This is a shallow copy. It is enough for immutable String values. If the list contains mutable records, their fields can still be shared and changed unless those values are copied too.
A getter can leak ownership
Returning the internal mutable list gives callers a route around the object’s validation methods. An unmodifiable wrapper blocks writes through that wrapper but still reflects changes made through another reference to the backing list.
Choose a snapshot, read-only live view, or explicitly shared collection according to the contract. The choice affects both memory and what a reader can observe over time. Hiding fields with private does not by itself establish that contract.
Connected lessons
Continue with Java inheritance and method overriding, Java Tutorial.
Common Mistakes
An unmodifiable wrapper around the original list is a view, not a snapshot. This class is not thread-safe; copying while another thread writes requires coordination.
