Skip to main content

Java OOP

Encapsulation

Complete lesson for Encapsulation using LEARNCODEGURU’s 6-level learning model — from basics to advanced practice, with Java OOP and Collections where relevant.

L1

Basics — Encapsulation

Section: Java OOP. Hide fields, expose a small API: private data, getters/setters, JavaBeans, and immutability.

What encapsulation is

  • Bundle state + behavior, and **hide** the representation. Callers use methods; they should not depend on field layout.
  • The usual pattern: private fields, public methods, validate in setters/constructors.
  • Access modifiers (private, package, protected, public) are the language tool; encapsulation is the design goal.
public class BankAccount {
    private double balance;

    public BankAccount(double opening) {
        if (opening < 0) throw new IllegalArgumentException("opening");
        this.balance = opening;
    }

    public double getBalance() {
        return balance;
    }

    public void deposit(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("amount");
        balance += amount;
    }

    public static void main(String[] args) {
        BankAccount a = new BankAccount(100);
        a.deposit(50);
        System.out.println(a.getBalance());
    }
}

Getters, setters, and JavaBeans

  • getX / isX (boolean) / setX is the JavaBean convention. Frameworks (Spring, JPA) still rely on it.
  • You do not owe a setter for every field. Read-only properties are better than public fields.
ExposureRiskPrefer
public int age;Anyone can set -3private + constructor / setter checks
Getter + setter, no checksSame as a public fieldValidate or drop the setter
Getter onlySafe if field is immutable / primitiveGood default
record / final fieldsNo accidental mutationJava 16+ data carriers

Returning mutable state

  • If a getter returns a live List or array, callers can mutate internals. Return a copy or an unmodifiable view (List.copyOf).
L2

Advanced — Encapsulation

Immutability and records

  • An immutable class: private final fields, no setters, defensive copies of mutable inputs/outputs, final class (or sealed) so subclasses cannot add mutators.
  • String, Integer, and java.time types are the standard library’s immutability lesson.
  • Encapsulation ≠ just private fields. A class with 20 getters that leak a web of objects is still poorly encapsulated.
L3

Tricky Interview Points

Q1) What is encapsulation?

Answer Hiding internal representation and exposing a controlled API. In Java this is mostly private fields plus methods that maintain invariants.

Q2) Why not public fields?

Answer You cannot validate, log, make thread-safe, or change representation later without breaking callers.

Q3) Is a getter/setter the same as a public field?

Answer If the setter has no rules, it is almost the same at runtime — but you can add rules later without changing the field to a method in every caller.

Q4) How do you encapsulate a List field?

Answer Store a private list, expose List.copyOf or unmodifiableList, or specific methods addItem/removeItem. Do not return the raw field.

Q5) What is a JavaBean?

Answer A convention: no-arg constructor, private fields, getters/setters, often Serializable. Used by many libraries.

Q6) How do records relate?

Answer A record is a transparent immutable carrier. It encapsulates storage but advertises its components. Use a class when you need a richer invariant.

L4

Simple Programs

Defensive copy of a list

import java.util.ArrayList;
import java.util.List;

public class Team {
    private final List<String> members = new ArrayList<>();

    public void add(String name) {
        members.add(name);
    }

    public List<String> getMembers() {
        return List.copyOf(members);
    }

    public static void main(String[] args) {
        Team t = new Team();
        t.add("Asha");
        List<String> view = t.getMembers();
        try {
            view.add("hack");
        } catch (UnsupportedOperationException e) {
            System.out.println("encapsulated");
        }
        System.out.println(t.getMembers());
    }
}
L5

Problem Solving Tricks

  • Put invariants in the constructor *and* every mutator.
  • Prefer verbs (deposit) over setBalance when the operation is not a raw assign.
  • record for dumb data; class + private fields for rules.
  • Package-private is encapsulation too — hide types that are not your public API.
L6

Practice Programs List

  1. Convert a class with public fields into private fields + getters and a validating setter.
  2. Write an immutable Fraction (final numerator/denominator, reduced in the constructor).
  3. Expose a Date or LocalDate field safely (hint: LocalDate is already immutable).
  4. Break encapsulation on purpose by returning the internal list, then fix it with List.copyOf.
  5. Document the invariant “balance never negative” and write a withdraw method that enforces it.