Encapsulation in Java
Encapsulation is the mechanism of restricting direct access to some of the object's components and only allowing access through certain methods.
This is typically achieved using access modifiers.
Encapsulation ensures that the internal representation of an object is hidden from the outside.
It helps in bundling the data (variables) and the methods (functions) that operate on the data into a single unit called a class.
Key Characteristics of Encapsulation
Data Hiding: Restricts access to certain details of an object to protect the object’s integrity.
Control: Provides controlled access to the object's data.
Simplification: Makes the code easier to maintain and understand.
Flexibility: Allows changes to the internal implementation without affecting the external code.
Access Modifiers
Java provides four access modifiers to specify the level of access control:
private: The member is accessible only within the same class.
default (package-private): The member is accessible only within the same package.
protected: The member is accessible within the same package and subclasses.
public: The member is accessible from any other class.
Example of Encapsulation
Let’s look at an example to understand how to achieve encapsulation in Java.
Defining a Class with Encapsulation
class Account {
// Private instance variables
private String accountNumber;
private double balance;
// Constructor to initialize account
public Account(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
}
// Public method to get the account number
public String getAccountNumber() {
return accountNumber;
}
// Public method to get the balance
public double getBalance() {
return balance;
}
// Public method to deposit money
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: " + amount);
} else {
System.out.println("Invalid deposit amount");
}
}
// Public method to withdraw money
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrawn: " + amount);
} else {
System.out.println("Invalid withdraw amount");
}
}
}
Using the Encapsulated Class
public class Main {
public static void main(String[] args) {
// Creating an object of the Account class
Account myAccount = new Account("123456789", 1000.00);
// Accessing the account details using public methods
System.out.println("Account Number: " + myAccount.getAccountNumber());
System.out.println("Initial Balance: " + myAccount.getBalance());
// Depositing money
myAccount.deposit(500.00);
System.out.println("Updated Balance: " + myAccount.getBalance());
// Withdrawing money
myAccount.withdraw(200.00);
System.out.println("Updated Balance: " + myAccount.getBalance());
// Attempting invalid operations
myAccount.deposit(-100.00);
myAccount.withdraw(2000.00);
}
}
Explanation:
Private Instance Variables: accountNumber and balance are declared as private, restricting direct access from outside the class.
Public Methods: getAccountNumber(), getBalance(), deposit(), and withdraw() provide controlled access to the private variables.
Constructor: Initializes the account with the given account number and initial balance.
Validation: The deposit() and withdraw() methods include validation to ensure that only valid operations are performed.
The output will be:
Account Number: 123456789
Initial Balance: 1000.0
Deposited: 500.0
Updated Balance: 1500.0
Withdrawn: 200.0
Updated Balance: 1300.0
Invalid deposit amount
Invalid withdraw amount
Benefits of Encapsulation
Improved Security: By restricting direct access to sensitive data, encapsulation helps protect the data from unauthorized access and modifications.
Data Integrity: Encapsulation ensures that the internal state of an object is only changed in a controlled manner.
Modularity: Classes with well-defined interfaces can be reused and modified independently.
Maintenance: Encapsulation makes the code easier to maintain and update. Changes to the internal implementation do not affect the external code.
Encapsulation in Action: Real-world Example
Consider a scenario where we have a class Employee with encapsulated fields and methods to access and update the employee details.
class Employee {
// Private instance variables
private int employeeId;
private String name;
private double salary;
// Constructor to initialize employee details
public Employee(int employeeId, String name, double salary) {
this.employeeId = employeeId;
this.name = name;
this.salary = salary;
}
// Public method to get the employee ID
public int getEmployeeId() {
return employeeId;
}
// Public method to get the employee name
public String getName() {
return name;
}
// Public method to get the employee salary
public double getSalary() {
return salary;
}
// Public method to set the employee name
public void setName(String name) {
this.name = name;
}
// Public method to set the employee salary
public void setSalary(double salary) {
if (salary > 0) {
this.salary = salary;
} else {
System.out.println("Invalid salary amount");
}
}
}
public class Main {
public static void main(String[] args) {
// Creating an object of the Employee class
Employee emp = new Employee(101, "John Doe", 50000.00);
// Accessing and updating employee details using public methods
System.out.println("Employee ID: " + emp.getEmployeeId());
System.out.println("Employee Name: " + emp.getName());
System.out.println("Employee Salary: " + emp.getSalary());
// Updating employee details
emp.setName("Jane Doe");
emp.setSalary(55000.00);
// Displaying updated employee details
System.out.println("Updated Employee Name: " + emp.getName());
System.out.println("Updated Employee Salary: " + emp.getSalary());
// Attempting invalid operations
emp.setSalary(-10000.00);
}
}
Explanation:
Private Instance Variables: employeeId, name, and salary are declared as private, restricting direct access from outside the class.
Public Methods: getEmployeeId(), getName(), getSalary(), setName(), and setSalary() provide controlled access to the private variables.
Validation: The setSalary() method includes validation to ensure that only valid salary amounts are set.
The output will be:
Employee ID: 101
Employee Name: John Doe
Employee Salary: 50000.0
Updated Employee Name: Jane Doe
Updated Employee Salary: 55000.0
Invalid salary amount
Summary
Encapsulation: Encapsulation is the process of bundling the data (variables) and the methods (functions) that operate on the data into a single unit called a class. It restricts direct access to some of the object's components.
Access Modifiers: Java provides access modifiers (private, default, protected, public) to control the visibility of class members.
Private Variables: Encapsulation typically involves making the instance variables private and providing public getter and setter methods to access and update the variables.
Benefits: Improved security, data integrity, modularity, and maintainability.
Encapsulation is a fundamental concept in Java that helps in creating robust and maintainable code. It ensures that the internal representation of an object is hidden from the outside, providing controlled access to the object's data and behavior.