Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java encapsulation and object ownership

Last updated: 29 Sept 20264 min read
tutorial
By AITrove Editorial

Encapsulation keeps an object’s representation behind operations that preserve its rules.

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

Java
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.

Protect every mutation route

Private fields are only one part of encapsulation. A public setter, returned array, live collection view or callback can still permit callers to bypass the intended invariant. Review the whole public surface and every alias it publishes.

Expose an operation such as reserve(quantity) when the rule spans available and reserved counts. Two unrelated setters make the caller responsible for preserving a relation it cannot update atomically. Validate before changing either field and specify the unchanged state on rejection.

An unmodifiable wrapper prevents updates through that wrapper but can still reflect owner updates and expose mutable elements. Independent snapshots need a copy at the correct layer. If multiple workers share the object, the class also needs one stated synchronization rule for reads and compound writes.

java
encapsulation
Storage details