← Back to Home

Encapsulation

Encapsulation is an object-oriented design principle that bundles data (variables) and behavior (methods) into a single unit (class) and restricts direct access to the data. It is achieved using access modifiers and getter/setter methods. This is a high-frequency interview topic and foundational for secure, maintainable Java design.

What Is Encapsulation?

  • Wrapping data and methods into a single class
  • Hiding internal state from external access
  • Exposing controlled access via methods

In simple terms: Protect the data, expose behavior.

Why Encapsulation Is Important

  • Improves data security
  • Prevents invalid state changes
  • Enhances maintainability
  • Supports flexibility and refactoring
  • Enables validation and business rules

How Encapsulation Is Achieved in Java

  1. Declare variables as private
  2. Provide public getter and setter methods
  3. Apply validation logic inside setters

Basic Encapsulation Example

class Student {
    private int age;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }
}
          

Usage

Student s = new Student();
s.setAge(20);
System.out.println(s.getAge());
          
  • Direct access is restricted
  • Data is modified only through controlled methods

What Happens Without Encapsulation (Bad Design)

class Student {
    public int age;
}

Student s = new Student();
s.age = -10; // invalid state
          
  • ❌ No control
  • ❌ No validation
  • ❌ Poor design

Encapsulation vs Data Hiding (Clarification)

Concept Meaning
Encapsulation Wrapping data + methods
Data Hiding Restricting direct access using private
  • Encapsulation includes data hiding
  • Data hiding alone is not full encapsulation

Access Modifiers and Encapsulation

Modifier Scope
private Within class only
default Same package
protected Package + subclass
public Everywhere

Best Practice:

  • Variables → private
  • Methods → public (controlled access)

Encapsulation with Validation Logic

class BankAccount {
    private double balance;
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }
    public double getBalance() {
        return balance;
    }
}
          
  • Business rules enforced
  • Invalid operations blocked

Read-Only and Write-Only Encapsulation

Read-Only Class

class Employee {
    private int id = 101;
    public int getId() {
        return id;
    }
}
          

Write-Only Class

class Password {
    private String pwd;
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}
          

Encapsulation and Immutability (Related Concept)

final class User {
    private final String name;
    User(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
          
  • Strong encapsulation
  • Object state cannot change

Encapsulation Benefits in Real Projects

  • Easier refactoring (internal change without breaking callers)
  • Better debugging and testing
  • Safer multi-team development
  • Cleaner APIs and contracts

Common Beginner Mistakes

  • Making variables public
  • Writing getters/setters without validation
  • Exposing internal objects directly
  • Confusing encapsulation with abstraction

Interview-Ready Answers

Short Answer

Encapsulation is the process of wrapping data and methods into a single unit and restricting direct access to data.

Detailed Answer

In Java, encapsulation is achieved by declaring class variables as private and providing controlled access through public getter and setter methods. It improves security, prevents invalid data modification, and enhances maintainability.

Key Takeaway

Encapsulation protects object integrity. It enforces controlled access, valid states, and clean design, making Java applications robust and maintainable.

Encapsulation Examples (Interview Practice)

1. Basic Encapsulation (Private Variable + Getter/Setter)

class User {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class Test {
    public static void main(String[] args) {
        User u = new User();
        u.setName("Admin");
        System.out.println(u.getName());
    }
}
          

Explanation

  • Data hidden using private
  • Controlled access via methods
  • Output: Admin

2. Direct Access Not Allowed

class User {
    private int age;
}

class Test {
    public static void main(String[] args) {
        User u = new User();
        // u.age = 20;  // Compile-time error
    }
}
          

Explanation

  • Encapsulation prevents direct field access

3. Validation Inside Setter

class User {
    private int age;

    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }

    public int getAge() {
        return age;
    }
}

class Test {
    public static void main(String[] args) {
        User u = new User();
        u.setAge(-5);
        System.out.println(u.getAge());
    }
}
          

Explanation

  • Business rule enforced
  • Output: 0

4. Read-Only Property (No Setter)

class Config {
    private final String env = "PROD";

    public String getEnv() {
        return env;
    }
}

class Test {
    public static void main(String[] args) {
        Config c = new Config();
        System.out.println(c.getEnv());
    }
}
          

Explanation

  • Encapsulation + immutability
  • Output: PROD

5. Write-Only Property (No Getter)

class Secret {
    private String password;

    public void setPassword(String password) {
        this.password = password;
    }
}
          

Explanation

  • Data can be written but not read

6. Encapsulation with Multiple Fields

class Employee {
    private int id;
    private String name;

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDetails() {
        return id + " " + name;
    }
}

class Test {
    public static void main(String[] args) {
        Employee e = new Employee();
        e.setId(101);
        e.setName("John");
        System.out.println(e.getDetails());
    }
}
          

Explanation

  • Multiple private fields
  • Output: 101 John

7. Constructor + Encapsulation

class Account {
    private double balance;

    public Account(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }
}

class Test {
    public static void main(String[] args) {
        Account a = new Account(1000);
        System.out.println(a.getBalance());
    }
}
          

Explanation

  • Initialization controlled
  • Output: 1000.0

8. Controlled Update Method (No Setter)

class Account {
    private double balance;

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    public double getBalance() {
        return balance;
    }
}

class Test {
    public static void main(String[] args) {
        Account a = new Account();
        a.deposit(500);
        System.out.println(a.getBalance());
    }
}
          

Explanation

  • Domain logic inside class
  • Output: 500.0

9. Encapsulation with Boolean Flag

class Feature {
    private boolean enabled;

    public boolean isEnabled() {
        return enabled;
    }

    public void enable() {
        enabled = true;
    }
}

class Test {
    public static void main(String[] args) {
        Feature f = new Feature();
        f.enable();
        System.out.println(f.isEnabled());
    }
}
          

Explanation

  • Standard isX() naming
  • Output: true

10. Encapsulation Prevents Invalid State

class Product {
    private int price;

    public void setPrice(int price) {
        if (price > 0) {
            this.price = price;
        }
    }

    public int getPrice() {
        return price;
    }
}

class Test {
    public static void main(String[] args) {
        Product p = new Product();
        p.setPrice(-100);
        System.out.println(p.getPrice());
    }
}
          

Explanation

  • Invalid data blocked
  • Output: 0

11. Encapsulation with Object Field

class Address {
    String city;
}

class User {
    private Address address;

    public void setAddress(Address address) {
        this.address = address;
    }

    public Address getAddress() {
        return address;
    }
}

class Test {
    public static void main(String[] args) {
        Address a = new Address();
        a.city = "Dallas";

        User u = new User();
        u.setAddress(a);

        System.out.println(u.getAddress().city);
    }
}
          

Explanation

  • Object encapsulated
  • Output: Dallas

12. Defensive Copy (Strong Encapsulation)

class User {
    private int[] scores;

    public void setScores(int[] scores) {
        this.scores = scores.clone();
    }

    public int[] getScores() {
        return scores.clone();
    }
}

class Test {
    public static void main(String[] args) {
        int[] arr = {10, 20};
        User u = new User();
        u.setScores(arr);

        arr[0] = 99;
        System.out.println(u.getScores()[0]);
    }
}
          

Explanation

  • Prevents external modification
  • Output: 10

13. Encapsulation + final Class

final class Constants {
    private int x = 10;

    public int getX() {
        return x;
    }
}
          

Explanation

  • Cannot be extended
  • Strong encapsulation

14. Encapsulation with Lazy Initialization

class Config {
    private String value;

    public String getValue() {
        if (value == null) {
            value = "DEFAULT";
        }
        return value;
    }
}

class Test {
    public static void main(String[] args) {
        Config c = new Config();
        System.out.println(c.getValue());
    }
}
          

Explanation

  • Value created only when needed
  • Output: DEFAULT

15. Encapsulation in Real-World Example (Login)

class Login {
    private String password = "admin123";

    public boolean authenticate(String input) {
        return password.equals(input);
    }
}

class Test {
    public static void main(String[] args) {
        Login l = new Login();
        System.out.println(l.authenticate("admin123"));
    }
}
          

Explanation

  • Password hidden
  • Output: true

16. Encapsulation + Method Chaining

class User {
    private String name;

    public User setName(String name) {
        this.name = name;
        return this;
    }

    public String getName() {
        return name;
    }
}

class Test {
    public static void main(String[] args) {
        User u = new User().setName("QA");
        System.out.println(u.getName());
    }
}
          

Explanation

  • Fluent API
  • Output: QA

17. Encapsulation Across Packages (Conceptual)

class User {
    private int id;
    protected String role;
}
          

Explanation

  • private → class only
  • protected → same package or subclass

18. Encapsulation Prevents Tight Coupling

class Engine {
    private int power = 100;

    public int getPower() {
        return power;
    }
}

class Car {
    private Engine engine = new Engine();

    public int getCarPower() {
        return engine.getPower();
    }
}
          

Explanation

  • Internal structure hidden

19. Bad Encapsulation Example (❌ Avoid)

class User {
    public int age;
}
          

Explanation

  • Data exposed directly
  • No control or validation

20. Interview Summary – Encapsulation

class User {
    private int age;

    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }

    public int getAge() {
        return age;
    }
}

class Test {
    public static void main(String[] args) {
        User u = new User();
        u.setAge(25);
        System.out.println(u.getAge());
    }
}
          

Explanation

  • Hide data
  • Expose behavior
  • Output: 25