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
- Declare variables as private
- Provide public getter and setter methods
- 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