0% found this document useful (0 votes)
7 views11 pages

Encapsulation

Encapsulation is a fundamental principle of Object-Oriented Programming that involves bundling data and methods within a class while restricting direct access to the internal data, ensuring data integrity and controlled modification. It is crucial for maintaining object integrity, easier maintenance, and better modularity in software systems. In Java, encapsulation is achieved through access modifiers, getters and setters, and immutability, with common pitfalls including returning mutable objects and excessive public access.

Uploaded by

johnytensa
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views11 pages

Encapsulation

Encapsulation is a fundamental principle of Object-Oriented Programming that involves bundling data and methods within a class while restricting direct access to the internal data, ensuring data integrity and controlled modification. It is crucial for maintaining object integrity, easier maintenance, and better modularity in software systems. In Java, encapsulation is achieved through access modifiers, getters and setters, and immutability, with common pitfalls including returning mutable objects and excessive public access.

Uploaded by

johnytensa
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Encapsulation

Java Edition — with Interview Insights

1. Introduction
Encapsulation is one of the four fundamental principles of Object-Oriented Programming (OOP):
• Encapsulation
• Abstraction
• Inheritance
• Polymorphism

Encapsulation refers to bundling data and the methods that operate on that data into a single
unit (class) while restricting direct access to the internal data.
The primary goal is to protect the integrity of the object's state and ensure that data can only be
modified through controlled methods.

Simple Definition
Encapsulation is the practice of wrapping data and methods together and controlling
access to that data.

Example: A bank account should not allow anyone to directly modify the balance:

[Link] = -100000; // BAD — direct field access

Instead, the system should enforce rules through methods:

[Link](100); // GOOD — controlled, validated access

🎯 Interview Tip
Encapsulation is NOT just about making fields private. It is about designing controlled
interfaces to protect object integrity.
A common interview follow-up: 'Can you have encapsulation without OOP?' — Yes, in C you
can use structs + function pointers, but OOP formalizes it with language-level support.

2. Why Encapsulation is Important in LLD


Encapsulation is extremely important when designing large software systems.
1. Data Protection
Internal object data cannot be modified directly.

BankAccount
├── balance (private)
├── deposit()
└── withdraw()

2. Maintaining Object Integrity


Encapsulation ensures that the object always stays in a valid state.

// Without encapsulation
[Link] = -500; // Allowed — invalid state!

// With encapsulation
[Link](500); // Validated inside — safe

3. Easier Maintenance
Internal implementation can change without affecting external code.

// Today: balance stored in a variable


// Tomorrow: balance fetched from a database
// External code remains the same:
[Link]();

4. Better Modularity
Encapsulation divides the system into self-contained modules. Each class manages its own
data.
• UserService
• PaymentService
• NotificationService
• RideService
Each service encapsulates its internal logic.

💡 Hidden/Often Forgotten
Encapsulation enables loose coupling. When class internals are hidden, other classes depend
only on the public interface — not on implementation details. This is foundational for SOLID
design.
It also enables thread safety: if state changes go through controlled methods, you can add
synchronization in one place instead of everywhere.
3. How Encapsulation is Achieved in Java
Encapsulation in Java is implemented using:
1. Access Modifiers
2. Getters and Setters
3. Data Hiding
4. Controlled Methods
5. Immutability (Java-specific — discussed below)

4. Access Modifiers in Java


Java provides four access modifiers (one more than C++).

Modifier Class Package Subclass Everywhere


private

default (no keyword)


protected

public

💡 Hidden/Often Forgotten
Java has a 4th modifier C++ doesn't — package-private (default, no keyword). If you declare a
field without any modifier, it is accessible to all classes in the same package but hidden from
outside.
This is widely used in well-structured Java codebases and is almost never mentioned in
beginner tutorials.
Example: int balance; // package-private — not private, not public!

Example: Encapsulation with Private Data

public class BankAccount {

private String accountHolder;


private double balance;

public BankAccount(String name, double bal) {


[Link] = name;
[Link] = bal;
}

public double getBalance() {


return balance;
}

public void deposit(double amount) {


if (amount > 0) {
balance += amount;
[Link]("Deposited: " + amount);
} else {
[Link]("Invalid deposit amount");
}
}
}

public class Main {


public static void main(String[] args) {
BankAccount account = new BankAccount("Alice", 1000);
[Link]("Current Balance: " + [Link]());
[Link](500);
[Link]("Updated Balance: " + [Link]());
}
}

Output:

Current Balance: 1000.0


Deposited: 500.0
Updated Balance: 1500.0

5. Encapsulation Using Getters and Setters


Instead of allowing direct access to variables, encapsulation uses getter and setter methods.

Getters
Used to read data safely.

public String getName() { return name; }

Setters
Used to validate and modify data. Validation can be applied before updating values.

public void setAge(int age) { ... }

Example:

public class Employee {


private String name;
private int age;

public String getName() { return name; }

public void setName(String newName) {


if (newName != null && ![Link]()) {
[Link] = newName;
}
}

public int getAge() { return age; }

public void setAge(int newAge) {


if (newAge > 18) {
[Link] = newAge;
} else {
[Link]("Age must be greater than 18");
}
}
}

🎯 Interview Tip
'What is the difference between a JavaBean and a POJO?' — A JavaBean is a POJO that
strictly follows encapsulation: private fields, public getters/setters, and a no-arg constructor.
Interviewers often ask this in Spring/framework contexts.
Frameworks like Spring, Hibernate, and Jackson rely on getters/setters for serialization,
dependency injection, and ORM mapping. Without proper encapsulation, these frameworks
break silently.

💡 Hidden/Often Forgotten
Lombok (@Data, @Getter, @Setter) auto-generates getters/setters at compile time. You'll see
this in most modern Java codebases. Know that it still enforces encapsulation — it just
removes boilerplate.
Be careful with setters: if every field has a public setter, your class is effectively mutable and
encapsulation is weakened. Prefer builders or constructors for initialization where possible.

6. Encapsulation and Immutability (Java-Specific)


Java offers a powerful pattern beyond basic encapsulation: Immutable classes. Once created,
the object's state cannot change at all.

How to create an Immutable class in Java:


• Declare the class as final (prevents subclassing)
• Make all fields private and final
• No setters
• Initialize all fields via constructor
• Return deep copies of mutable objects in getters

public final class ImmutableBankAccount {

private final String accountHolder;


private final double balance;

public ImmutableBankAccount(String holder, double balance) {


[Link] = holder;
[Link] = balance;
}

public String getAccountHolder() { return accountHolder; }


public double getBalance() { return balance; }

// Return a NEW object instead of modifying


public ImmutableBankAccount deposit(double amount) {
return new ImmutableBankAccount(accountHolder, balance + amount);
}
}

🎯 Interview Tip
Why is String immutable in Java? — Classic interview question. Answer: Security (can't alter
string after creation), thread safety (shared safely), and string pool optimization (same literal
reused in heap).
Immutability is the strongest form of encapsulation — not even the object itself can change
state after construction.
Java 16+ Records are a concise way to create immutable data classes: public record Point(int
x, int y) {} — fields are automatically private final with getters.

7. Encapsulation and Data Hiding


Encapsulation also hides internal helper methods from external callers.
The user only calls: withdraw()
The internal validation is hidden: validateWithdrawal()

public class Account {

private double balance;

public Account(double initialBalance) {


[Link] = initialBalance;
}

private boolean validateWithdrawal(double amount) {


return amount > 0 && amount <= balance;
}

public void withdraw(double amount) {


if (validateWithdrawal(amount)) {
balance -= amount;
[Link]("Withdrawal Successful: " + amount);
} else {
[Link]("Insufficient balance or invalid amount");
}
}

public double getBalance() { return balance; }


}

💡 Hidden/Often Forgotten
In Java, you can also hide classes themselves using package-private class declarations (no
public keyword). This is useful in large systems to expose only the minimum API surface.
Helper/utility classes internal to a package are often intentionally kept package-private, so
external modules can never depend on them.

8. Encapsulation in Real World Systems


1. Banking Systems
BankAccount
├── balance (private)
├── deposit()
└── withdraw()

2. Healthcare Systems
PatientRecord
├── medicalHistory (private)
├── diagnosis (private)
└── prescriptions (private)

Access is controlled through secure APIs.

3. E-Commerce Systems
public class PaymentProcessor {
private String cardNumber;
private double amount;

public PaymentProcessor(String card, double amt) {


[Link] = card;
[Link] = amt;
}

private String maskCardNumber(String cardNumber) {


return "****-****-****-" + [Link]([Link]() - 4);
}

public void processPayment() {


[Link]("Processing payment of " + amount
+ " for card " + maskCardNumber(cardNumber));
}
}

Output:

Processing payment of 250.0 for card ****-****-****-5678

9. Encapsulation vs Abstraction
This is a very common interview question.

Feature Encapsulation Abstraction


Focus Protecting data Hiding complexity
Purpose Data security Simplifying interface
Implementation Access modifiers, getters/setters Abstract classes / Interfaces
Question Answered How data is protected What functionality is exposed
Java example private int balance; interface Payment { void
process(); }

Java Example — Encapsulation:

private int balance;

Java Example — Abstraction:

public interface PaymentGateway {


void processPayment(double amount);
}
🎯 Interview Tip
They often overlap: a well-encapsulated class hides its fields (encapsulation) AND exposes
only a clean interface (abstraction). They are complementary, not competing.
A common trick question: 'Is an interface encapsulation or abstraction?' — It is primarily
abstraction (defining what, not how), but implementing it with a concrete class involves
encapsulation (hiding how).
Follow-up: 'Can you have abstraction without encapsulation?' — Technically yes (e.g., public
abstract method with public fields), but it's bad design and defeats the purpose.

10. Defensive Copying — The Hidden Encapsulation Pitfall


One of the most frequently missed encapsulation mistakes in Java: returning mutable objects
from getters breaks encapsulation silently.

import [Link];
import [Link];

public class Order {


private List<String> items = new ArrayList<>();

public void addItem(String item) { [Link](item); }

// BAD: returning direct reference — caller can mutate our list!


public List<String> getItems() { return items; }

// GOOD: return a defensive copy


public List<String> getItems() { return new ArrayList<>(items); }

// BEST (Java 9+): return an unmodifiable view


public List<String> getItems() { return [Link](items); }
}

💡 Hidden/Often Forgotten
This mistake is extremely common in real codebases. Even experienced developers miss it.
The same applies to Date objects. If you store a Date field and return it directly, callers can call
setTime() on it and mutate your object's state from outside!
Java 8+ solution: Use LocalDate / LocalDateTime (immutable) instead of [Link] to avoid
this problem entirely.

11. Common Mistakes


1. Making Everything Public
public int balance; // BAD

2. Too Many Getters and Setters


If every field has a getter and setter, encapsulation becomes meaningless — the class is
effectively public.

// BAD: exposes internal state freely


setBalance(double balance)

// GOOD: expose behavior, not state


deposit(double amount)
withdraw(double amount)

3. Violating Object Responsibility


Letting unrelated classes manage each other's data breaks encapsulation.
• Bad: User class managing payment logic
• Good: User + PaymentService (separate responsibilities)

4. Leaking Mutable Internal State (See Section 10)


Returning direct references to internal collections or mutable objects.

5. Exposing Implementation Through Method Names


// BAD: exposes that you're using an ArrayList internally
public ArrayList<String> getItemList()

// GOOD: expose only the interface


public List<String> getItems()

🎯 Interview Tip
'Tell the Law of Demeter' — also called the Principle of Least Knowledge. A method should
only call methods on: itself, its parameters, objects it creates, and its direct fields. Calling
methods on returned objects ([Link]().getC().doSomething()) violates encapsulation.
Example of a violation: [Link]().getCity().toUpperCase() — you are depending on the
internals of Address and City.
Fix: [Link]() — the User class encapsulates navigation to the city internally.

12. Key Takeaways


• Encapsulation ensures that object data remains protected
• Invalid states are prevented through controlled access methods
• System becomes modular and maintainable
• Internal implementation can change without breaking external code
• Java's 4th modifier (package-private / default) is a powerful, often overlooked tool
• Immutability is the strongest form of encapsulation — use final fields and no setters
• Always return defensive copies or unmodifiable views of mutable fields
• Encapsulation and abstraction are complementary, not competing

✅ Golden Line
Encapsulation protects an object's internal state by restricting direct access to its data —
and in Java, the strongest form is immutability.

You might also like