Table of Contents
- Introduction to Encapsulation
- Benefits of Encapsulation
- How Encapsulation Works in Java
- Access Modifiers in Java
- Public
- Private
- Protected
- Default (Package-Private)
- Choosing the Right Access Modifier
- Encapsulation in Action: Code Examples
- Summary
1. Introduction to Encapsulation
Encapsulation is one of the four fundamental principles of Object-Oriented Programming (OOP) — the others being inheritance, polymorphism, and abstraction. Encapsulation is the concept of wrapping or bundling the data (variables) and the methods (functions) that operate on the data into a single unit known as a class. It also involves restricting access to certain components of an object to ensure that the internal state is protected and only modified in a controlled manner.
By restricting direct access to the object’s data and providing controlled access through getter and setter methods, encapsulation helps protect the integrity of the object. This practice ensures that changes to an object’s state are done in a well-defined, predictable way, and unintended interference is avoided.
2. Benefits of Encapsulation
Encapsulation provides several key benefits that contribute to code maintainability, readability, and security:
a. Control over Data
Encapsulation allows you to control how the data in an object is accessed or modified. You can make certain fields read-only, write-only, or read-write, depending on the needs of your application.
b. Improved Maintainability
Since an object’s internal state is hidden, developers can change the internal implementation of an object without affecting its external interface. This promotes loose coupling and makes the code easier to maintain.
c. Increased Security
By hiding the internal implementation of an object, you can restrict access to sensitive data. This minimizes the risk of external code accidentally or maliciously altering the object’s state in an invalid way.
d. Better Data Integrity
Encapsulation helps maintain the integrity of the object’s state. For example, by using setter methods with validation, you can ensure that the object’s properties are only set to valid values, preventing invalid data from being assigned.
3. How Encapsulation Works in Java
In Java, encapsulation is achieved by making the instance variables of a class private and providing public getter and setter methods to access and update their values.
a. Private Variables
Variables within a class should be made private to ensure they cannot be directly accessed from outside the class. This restricts unauthorized access to the object’s state.
b. Public Getter and Setter Methods
These methods are used to provide controlled access to the private variables. A getter method returns the value of a private variable, while a setter method allows the modification of a private variable in a controlled manner.
Example:
public class Person {
// Private instance variables
private String name;
private int age;
// Getter method for 'name'
public String getName() {
return name;
}
// Setter method for 'name'
public void setName(String name) {
this.name = name;
}
// Getter method for 'age'
public int getAge() {
return age;
}
// Setter method for 'age'
public void setAge(int age) {
if(age > 0) {
this.age = age;
} else {
System.out.println("Age must be positive.");
}
}
}
In this example, name
and age
are private, and we access them via public getter and setter methods. The setter for age
includes validation to ensure the value is positive before assigning it.
4. Access Modifiers in Java
Access modifiers in Java determine the visibility and accessibility of classes, methods, and variables. Java provides four types of access modifiers, which are used to define the scope of access for class members.
a. Public Modifier
A public class, method, or variable is accessible from anywhere in the program. There are no restrictions on its access.
Example:
public class Example {
public int number;
public void display() {
System.out.println("Public method");
}
}
Here, the variable number
and the method display
are public and can be accessed from any class.
b. Private Modifier
A private variable or method is only accessible within the class in which it is declared. It cannot be accessed from outside the class, ensuring that the class’s internal state is hidden from other classes.
Example:
class Example {
private int number;
private void display() {
System.out.println("Private method");
}
public void accessPrivateMethod() {
display(); // Allowed inside the class
}
}
In this case, the method display()
and the variable number
are private and cannot be accessed from outside the Example
class.
c. Protected Modifier
A protected variable or method is accessible within the same package and by subclasses, even if they are in different packages.
Example:
class Animal {
protected String name;
protected void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
public void display() {
sound(); // Accessing protected method from superclass
System.out.println("Dog's name is: " + name);
}
}
Here, the name
variable and the sound()
method are protected, and can be accessed within the Dog
subclass, which extends the Animal
class.
d. Default (Package-Private) Modifier
If no access modifier is specified, the default access level is package-private (or default). This means the class, method, or variable is accessible only within the same package.
Example:
class Example {
int number; // default access modifier
void display() {
System.out.println("Default method");
}
}
Here, the variable number
and the method display()
have default access, meaning they can be accessed only within the same package.
5. Choosing the Right Access Modifier
Choosing the right access modifier is crucial for maintaining the integrity of an object’s state and the overall design of your system. Here are some general guidelines:
- Public: Use
public
for methods and variables that need to be accessed by any other class, such as utility methods or constants. - Private: Use
private
for variables and methods that should not be accessed from outside the class. This is essential for encapsulation and data protection. - Protected: Use
protected
when you want subclasses to access certain variables or methods but do not want them to be exposed outside the class hierarchy. - Default (Package-Private): Use default access when you want members to be accessible only within the same package.
6. Encapsulation in Action: Code Examples
Let’s look at a more comprehensive example demonstrating encapsulation in Java.
class BankAccount {
private double balance;
// Getter for balance
public double getBalance() {
return balance;
}
// Setter for balance
public void deposit(double amount) {
if(amount > 0) {
balance += amount;
} else {
System.out.println("Amount should be positive.");
}
}
public void withdraw(double amount) {
if(amount > 0 && amount <= balance) {
balance -= amount;
} else {
System.out.println("Invalid withdrawal amount.");
}
}
}
public class Main {
public static void main(String[] args) {
BankAccount account = new BankAccount();
account.deposit(1000); // Depositing money
account.withdraw(500); // Withdrawing money
System.out.println("Current balance: " + account.getBalance()); // Accessing balance through getter
}
}
In this example, the balance
is private, and its access is restricted to the getter and setter methods. The setter methods ensure that only valid values can be assigned to balance
, preserving the integrity of the object’s state.
7. Summary
In this module, we have explored encapsulation and access modifiers in Java. Encapsulation allows for better data protection, easier maintenance, and more flexible code. By using private variables and public getter and setter methods, you can ensure controlled access to an object’s internal state.
We have also looked at the different access modifiers (public
, private
, protected
, and default), each with its own use case for controlling visibility and access. Understanding when and how to use these modifiers is essential for creating robust and secure Java applications.