Encapsulation in Java – Complete Tutorial
Last Updated on: 17th Nov 2025 15:31:43 PM
Welcome to this beginner-friendly tutorial on Encapsulation in Java!
Encapsulation is one of the four fundamental principles of OOP (Object-Oriented Programming). It is the technique of bundling data (variables) and methods (behavior) that operate on the data into a single unit (class), and restricting direct access to some of the object’s components.
This tutorial uses a real-world project-based example — a Secure Online Banking System — to show how encapsulation is used in actual production applications.
What Is Encapsulation?
Encapsulation means wrapping data (variables) and code (methods) into a single unit (class) and restricting direct access to the data using access modifiers like private.
The data can be accessed only through public methods (getters & setters).
It means:
-
Keep the internal details (fields) of a class private
-
Provide public methods (getters/setters) to access or modify them safely
-
Hide how things work, expose only what is needed
Why Encapsulation Is Important?
✔ Protects sensitive data
✔ Helps achieve security
✔ Controls how data is read/modified
✔ Makes code maintainable
✔ Helps implement real-world objects correctly
✔ Avoids accidental changes in important fields
Why Use Encapsulation?
|
Benefit |
Explanation |
|---|---|
|
Data Protection |
Prevent invalid values (e.g., negative balance) |
|
Flexibility |
Change internal logic without breaking code |
|
Security |
Hide sensitive data (password, account number) |
|
Maintainability |
Easy to debug and update |
Encapsulation With Getters & Setters (Main Concept)
Encapsulation uses:
-
private variables → hidden from outside
-
public getter and setter methods → controlled access
Encapsulation Example
class BankAccount {
private String accountHolder; // private = data hiding
private double balance;
// Setter Method
public void setAccountHolder(String name) {
accountHolder = name;
}
// Getter Method
public String getAccountHolder() {
return accountHolder;
}
// Setter Method
public void setBalance(double amount) {
if (amount > 0) {
balance = amount;
} else {
System.out.println("Invalid Amount");
}
}
// Getter Method
public double getBalance() {
return balance;
}
}
public class Main {
public static void main(String[] args) {
BankAccount acc = new BankAccount();
acc.setAccountHolder("Amit Sharma");
acc.setBalance(50000);
System.out.println("Account Holder: " + acc.getAccountHolder());
System.out.println("Balance: ₹" + acc.getBalance());
}
}
Output:
Account Holder: Amit Sharma
Balance: ₹50000
Here:
-
accountHolderandbalanceare private, so no one can access them directly. -
Only allowed through getter & setter methods → controlled access.
Without Encapsulation (Bad Practice)
class Student {
public String name;
public int age;
}
public class Main {
public static void main(String[] args) {
Student s = new Student();
s.age = -10; // ❌ logically wrong
}
}
Anyone can change age to -10 or name to an empty value → not secure.
Encapsulation Fix (Proper Way)
class Student {
private String name;
private int age;
// Setter with validation
public void setAge(int a) {
if (a > 0) {
age = a;
} else {
System.out.println("Age must be positive");
}
}
public int getAge() {
return age;
}
}
Real-Time Project: Secure Online Banking System
Let’s build a BankAccount class with full encapsulation.
Step 1: Poor Design (Without Encapsulation)
// BAD EXAMPLE - NO ENCAPSULATION
public class BadBankAccount {
public String accountNumber = "ACC123";
public double balance = 10000;
public String pin = "1234";
public void withdraw(double amount) {
balance -= amount;
}
}
// Usage (Dangerous!)
BadBankAccount acc = new BadBankAccount();
acc.balance = -999999; // Allowed! Negative balance
acc.pin = "0000"; // Anyone can change PIN
System.out.println(acc.balance); // Direct access
→ Anyone can break the system!
Step 2: Perfect Encapsulation (Real Project Style)
// BankAccount.java - FULLY ENCAPSULATED
public class BankAccount {
// 1. Private fields - hidden from outside
private String accountNumber;
private String accountHolder;
private double balance;
private String pin;
private boolean isLocked = false;
private int failedAttempts = 0;
// 2. Public constructor
public BankAccount(String accountNumber, String accountHolder, String pin, double initialDeposit) {
this.accountNumber = accountNumber;
this.accountHolder = accountHolder;
this.pin = pin;
this.balance = initialDeposit;
System.out.println("Account created for " + accountHolder);
}
// 3. Public getter methods (Read-only access)
public String getAccountNumber() {
return accountNumber;
}
public String getAccountHolder() {
return accountHolder;
}
public double getBalance() {
return balance;
}
public boolean isLocked() {
return isLocked;
}
// 4. Public controlled methods (Safe operations)
public boolean authenticate(String enteredPin) {
if (isLocked) {
System.out.println("Account is locked. Contact bank.");
return false;
}
if (enteredPin.equals(this.pin)) {
failedAttempts = 0;
return true;
} else {
failedAttempts++;
if (failedAttempts >= 3) {
isLocked = true;
System.out.println("Too many wrong attempts! Account locked.");
}
System.out.println("Wrong PIN! Attempts: " + failedAttempts);
return false;
}
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: ₹" + amount + " | New Balance: ₹" + balance);
} else {
System.out.println("Invalid deposit amount");
}
}
public void withdraw(double amount, String pin) {
if (!authenticate(pin)) {
return;
}
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrawn: ₹" + amount + " | Remaining: ₹" + balance);
} else if (amount > balance) {
System.out.println("Insufficient balance!");
} else {
System.out.println("Invalid amount");
}
}
public void changePin(String oldPin, String newPin) {
if (!authenticate(oldPin)) {
return;
}
if (newPin.length() == 4 && newPin.matches("\\d+")) {
this.pin = newPin;
System.out.println("PIN changed successfully!");
} else {
System.out.println("New PIN must be 4 digits");
}
}
// Optional: Admin method (not public)
private void unlockAccount() {
isLocked = false;
failedAttempts = 0;
System.out.println("[ADMIN] Account unlocked");
}
}
Step 3: Main Application – OnlineBankingApp.java
// OnlineBankingApp.java
public class OnlineBankingApp {
public static void main(String[] args) {
System.out.println("SECURE ONLINE BANKING SYSTEM\n");
// Create account
BankAccount account = new BankAccount("SBI123456", "Rahul Sharma", "4567", 15000);
// Safe operations
account.deposit(5000);
account.withdraw(3000, "4567"); // Correct PIN
account.withdraw(3000, "9999"); // Wrong PIN
account.withdraw(3000, "8888"); // Wrong again
account.withdraw(3000, "7777"); // 3rd wrong → Account locked!
// Try after lock
account.withdraw(1000, "4567"); // Blocked
// Safe read
System.out.println("Balance: ₹" + account.getBalance());
System.out.println("Holder: " + account.getAccountHolder());
// Cannot do this! (Compile error)
// account.balance = -100000; // private!
// account.pin = "1111"; // private!
// account.isLocked = false; // private!
// Change PIN safely
account.changePin("4567", "8901");
System.out.println("\nEncapsulation protected the account!");
}
}
Output
SECURE ONLINE BANKING SYSTEM
Account created for Rahul Sharma
Deposited: ₹5000.0 | New Balance: ₹20000.0
Withdrawn: ₹3000.0 | Remaining: ₹17000.0
Wrong PIN! Attempts: 1
Wrong PIN! Attempts: 2
Too many wrong attempts! Account locked.
Account is locked. Contact bank.
Balance: ₹17000.0
Holder: Rahul Sharma
Account is locked. Contact bank.
New PIN must be 4 digits
Encapsulation protected the account!
Key Encapsulation Rules Followed
|
Rule |
Implemented? |
How |
|---|---|---|
|
Private fields |
Yes |
All data is private |
|
Public getters/setters |
Yes |
Controlled access |
|
Validation in methods |
Yes |
PIN check, amount check |
|
Hide internal logic |
Yes |
authenticate() is internal |
|
No direct field access |
Yes |
Impossible from outside |
Real Life Example of Encapsulation
-
ATM machine shows balance, but you cannot modify the bank’s balance directly.
-
All sensitive data is hidden behind methods.
-
You interact only through predefined functions like withdraw, deposit, check balance.
That is Encapsulation.
Benefits of Encapsulation
| Benefit | Description |
|---|---|
| Data Hiding | Prevents others from accessing sensitive data |
| Security | Protect data from unauthorized access |
| Controlled Access | Data can be accessed only via getters & setters |
| Improves Flexibility | You can change internal logic without affecting outer code |
| Clean Code | Better organization and maintainability |
When Should You Use Encapsulation?
Use it whenever:
-
Data needs protection (password, balance, age, salary)
-
You want control over how values are set
-
You want flexibility to change implementation later
-
You're building real-world systems (banking, HR, shopping cart, login system, etc.)
Conclusion
Encapsulation is a core pillar of OOP in Java.
It hides sensitive data using private and provides controlled access using public getters and setters.
It improves:
-
Security
-
Flexibility
-
Maintainability
-
Data integrity
Using encapsulation makes your code cleaner, safer, and more professional.
Project Tip:
In your Banking / E-commerce / Hospital app, always apply encapsulation to:
-
User credentials
-
Account balance
-
Patient records
-
Order details
-
Payment info
You now fully understand Encapsulation with a real-world secure banking system!
This is how professional Java developers write safe, maintainable code.
Keep practicing — happy coding! ![]()