Introduction
Object-Oriented Programming (OOP) is built on four core principles:
- Encapsulation
- Inheritance
- Polymorphism
- Abstraction
In this article, we'll explore Encapsulation, one of the most important concepts in Java, using a simple Expense Tracker application.
Understanding Encapsulation with a Real-Life Analogy
Imagine you're at a coffee shop.
If your money is kept in an open cash drawer on the counter, anyone can:
- Take money out
- Add fake money
- Accidentally damage it
You have no control over your cash.
A safer approach is keeping your money inside a wallet.
When the barista asks for $5, they don't reach into your pocket. Instead:
- They request the money.
- You verify the request.
- You hand over the correct amount.
This gives you complete control over how your money is accessed and modified.
Encapsulation works the same way in programming.
What is Encapsulation?
Encapsulation is the process of:
- Bundling data (variables) and behavior (methods) into a single unit (class).
- Restricting direct access to internal data.
- Providing controlled access through methods.
In Java, encapsulation is achieved by:
- Declaring variables as
private. - Providing
publicgetter and setter methods.
Why Do We Need Encapsulation?
Consider an Expense Tracker application.
Without encapsulation, anyone could set an expense amount to a negative value:
expense.amount = -500;
An expense of -500 doesn't make sense and can corrupt our application's data.
Encapsulation helps prevent such invalid operations.
Expense Class Example
public class Expense {
// Private fields
private String description;
private double amount;
// Constructor
public Expense(String description, double amount) {
this.description = description;
setAmount(amount);
}
// Getter for description
public String getDescription() {
return description;
}
// Setter for description
public void setDescription(String description) {
this.description = description;
}
// Getter for amount
public double getAmount() {
return amount;
}
// Setter with validation
public void setAmount(double amount) {
if (amount < 0) {
throw new IllegalArgumentException(
"Amount cannot be negative!"
);
}
this.amount = amount;
}
}
How Validation Protects Data
The setAmount() method contains validation logic:
if (amount < 0) {
throw new IllegalArgumentException(
"Amount cannot be negative!"
);
}
Now:
expense.setAmount(-10);
will throw an exception instead of storing invalid data.
This ensures the integrity of our Expense Tracker.
Interview Spotlight: Getters, Setters, and Encapsulation
Question
Why do we encapsulate data if we are just providing public getters and setters anyway? Isn't that the same as public variables?
Answer
No.
Public variables allow unrestricted modification of data.
Getters and setters provide control over how data is accessed and modified.
Benefits include:
1. Validation
if (amount < 0) {
throw new IllegalArgumentException();
}
Invalid values can be blocked before they enter the system.
2. Read-Only Fields
Provide only a getter and omit the setter.
public String getId() {
return id;
}
Now the value can be viewed but not modified.
3. Flexible Internal Implementation
Today:
private double amount;
Tomorrow:
private int amountInCents;
External code still uses:
expense.getAmount();
without any changes.
This makes applications easier to maintain and evolve.
Active Recall Challenge
Let's enhance our Expense Tracker by adding a category field.
Requirements:
- The field should be private.
- The field should have a getter.
- The field should have a setter.
- The setter should reject:
null- Empty strings (
"") - Strings containing only spaces
If the value is invalid, it should throw an IllegalArgumentException.
Solution
private String category;
public String getCategory() {
return category;
}
public void setCategory(String category) {
if (category == null || category.trim().isEmpty()) {
throw new IllegalArgumentException(
"Category cannot be null or empty!"
);
}
this.category = category;
}
Key Takeaways
- Encapsulation hides internal data from direct access.
- Private fields protect an object's state.
- Getters and setters provide controlled access to data.
- Validation inside setters helps maintain clean and reliable data.
- Encapsulation improves security, maintainability, and flexibility.
By mastering encapsulation, you build safer and more robust Java applications.
Top comments (0)