Encapsulation
Encapsulation is one of the core features of OOP. This lesson covers how to protect object data.
What is Encapsulation
Encapsulation bundles data (attributes) and methods that operate on that data together, hiding internal implementation details.
Benefits of Encapsulation
| Benefit | Description |
|---|---|
| Data protection | Prevents direct external access and modification |
| Flexibility | Can add validation logic in setters |
| Maintainability | Internal changes don't affect external calls |
Access Modifiers
Java has four access modifiers that control the visibility of classes, attributes, and methods.
| Modifier | Same Class | Same Package | Subclass | Different Package |
|---|---|---|---|---|
public |
✅ | ✅ | ✅ | ✅ |
protected |
✅ | ✅ | ✅ | ❌ |
| Default (no modifier) | ✅ | ✅ | ❌ | ❌ |
private |
✅ | ❌ | ❌ | ❌ |
Example: Access Modifiers
JAVA
public class Person {
public String name; // Public, accessible anywhere
protected int age; // Protected, accessible in same package and subclasses
String address; // Default, accessible in same package
private double salary; // Private, accessible only in this class
}
💡 Recommendation: Use
private for attributes and access them through getter/setter methods.
Getters and Setters
Why Getters/Setters are Needed
JAVA
public class Person {
private String name;
private int age;
// Getter
public String getName() {
return name;
}
// Setter
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
// Add validation logic in setter
if (age >= 0 && age <= 150) {
this.age = age;
} else {
System.out.println("Invalid age");
}
}
}
Example: Using Getters/Setters
JAVA
public class PersonTest {
public static void main(String[] args) {
Person p = new Person();
// Set values via setters
p.setName("Alice");
p.setAge(25);
// Get values via getters
System.out.println("Name: " + p.getName());
System.out.println("Age: " + p.getAge());
// Validation in setter
p.setAge(-5); // Output: Invalid age
}
}
JavaBean Conventions
JavaBean is a special type of Java class that follows specific conventions.
JavaBean Rules
| Rule | Description |
|---|---|
| Private attributes | Modified with private |
| Provide getters/setters | getXxx() and setXxx() |
| No-argument constructor | Required |
| Implement Serializable | Optional, for serialization |
Example: Standard JavaBean
JAVA
import java.io.Serializable;
public class User implements Serializable {
// Private attributes
private String username;
private String password;
private int age;
// No-argument constructor
public User() {}
// Parameterized constructor
public User(String username, String password, int age) {
this.username = username;
this.password = password;
this.age = age;
}
// Getters/Setters
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
if (password.length() >= 6) {
this.password = password;
} else {
System.out.println("Password must be at least 6 characters");
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 0 && age <= 150) {
this.age = age;
} else {
System.out.println("Invalid age");
}
}
@Override
public String toString() {
return "User{username='" + username + "', age=" + age + "}";
}
}
Encapsulation in Practice
Example: Bank Account
JAVA
public class BankAccount {
private String accountId;
private double balance;
private String owner;
public BankAccount(String accountId, String owner) {
this.accountId = accountId;
this.owner = owner;
this.balance = 0;
}
// Deposit
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: " + amount + ", Balance: " + balance);
} else {
System.out.println("Deposit amount must be greater than 0");
}
}
// Withdraw
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrawn: " + amount + ", Balance: " + balance);
} else if (amount > balance) {
System.out.println("Insufficient balance");
} else {
System.out.println("Withdrawal amount must be greater than 0");
}
}
// Check balance
public double getBalance() {
return balance;
}
public void showInfo() {
System.out.println("Account: " + accountId + ", Owner: " + owner + ", Balance: " + balance);
}
public static void main(String[] args) {
BankAccount account = new BankAccount("10001", "Alice");
account.showInfo(); // Account: 10001, Owner: Alice, Balance: 0.0
account.deposit(1000); // Deposited: 1000.0, Balance: 1000.0
account.deposit(500); // Deposited: 500.0, Balance: 1500.0
account.withdraw(200); // Withdrawn: 200.0, Balance: 1300.0
account.withdraw(2000); // Insufficient balance
}
}
Example: Product Price Validation
JAVA
public class Product {
private String name;
private double price;
private int stock;
public Product(String name, double price, int stock) {
this.name = name;
setPrice(price);
setStock(stock);
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
if (price >= 0) {
this.price = price;
} else {
System.out.println("Price cannot be negative");
}
}
public int getStock() {
return stock;
}
public void setStock(int stock) {
if (stock >= 0) {
this.stock = stock;
} else {
System.out.println("Stock cannot be negative");
}
}
// Calculate total price
public double getTotalPrice(int quantity) {
if (quantity > 0 && quantity <= stock) {
return price * quantity;
} else {
System.out.println("Invalid quantity");
return 0;
}
}
@Override
public String toString() {
return name + " - $" + price + " (Stock: " + stock + ")";
}
}
Getter/Setter Naming Rules
| Attribute Type | Getter | Setter |
|---|---|---|
boolean married |
isMarried() |
setMarried() |
String name |
getName() |
setName() |
int age |
getAge() |
setAge() |
⚠️ Special case: For
boolean types, the getter uses is prefix, not get.
❓ Frequently Asked Questions
Q Why not just use public attributes?
A Public attributes provide no access control. Setters can add validation logic to protect data integrity.
Q Do all attributes need getters/setters?
A Not necessarily. Read-only attributes only need getters. Write-only attributes only need setters.
Q What's the difference between constructors and setters?
A Constructors are called when creating objects. Setters modify attributes after the object is created.
📖 Summary
- Encapsulation hides internal implementation and protects data
- Use private for attributes, access through getters/setters
- Four access modifiers: public, protected, default, private
- JavaBean conventions: private attributes, getters/setters, no-argument constructor
📝 Exercises
- Student class: Define a Student class with encapsulated attributes, validate score between 0-100
- Date class: Define a date class with encapsulated year/month/day, provide date validation
- BankAccount improvement: Add password validation, require password for withdrawals
Next Lesson
In the next lesson, we'll learn about Inheritance — an important mechanism for code reuse.



