Encapsulation is one of the four main principles of Object-Oriented Programming (OOP). It means combining data and the methods that operate on that data inside a class while controlling access to the internal state.
Encapsulation is the process of wrapping variables and methods together in a class and restricting direct access to internal data when appropriate.
In Java, encapsulation is commonly achieved by:
private.class Student {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class Main {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("Rahul");
System.out.println(s1.getName());
}
}
Rahul
The private access modifier restricts
access to a field or method to within the class
where it is declared.
class Employee {
private int salary = 25000;
public void showSalary() {
System.out.println(salary);
}
}
class Main {
public static void main(String[] args) {
Employee e1 = new Employee();
e1.showSalary();
// This would cause a compilation error:
// System.out.println(e1.salary);
}
}
25000
The salary field cannot be accessed directly from the Main class because it is private.
A getter is a method used to read the value of a field.
class Student {
private String name = "Amit";
public String getName() {
return name;
}
}
class Main {
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(s1.getName());
}
}
Amit
The getName() method provides
controlled access to the private name field.
A setter is a method used to update a field's value.
class Student {
private int age;
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
class Main {
public static void main(String[] args) {
Student s1 = new Student();
s1.setAge(20);
System.out.println(s1.getAge());
}
}
20
The setter updates the private field, and the getter returns its current value.
The this keyword refers to the
current object. It is often used when a
parameter has the same name as a field.
class Student {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
class Main {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("Priya");
System.out.println(s1.getName());
}
}
Priya
this.name refers to the object's field,
while name refers to the method parameter.
A setter can validate input before storing it. This prevents invalid values from being accepted through that method.
class Student {
private int age;
public void setAge(int age) {
if (age >= 1 && age <= 100) {
this.age = age;
} else {
System.out.println("Invalid age");
}
}
public int getAge() {
return age;
}
}
class Main {
public static void main(String[] args) {
Student s1 = new Student();
s1.setAge(20);
System.out.println(s1.getAge());
s1.setAge(-5);
}
}
20
Invalid age
The setter accepts ages from 1 to 100 and rejects values outside that range.
class Employee {
private String name;
private double salary;
public void setName(String name) {
if (name != null && !name.isBlank()) {
this.name = name;
}
}
public String getName() {
return name;
}
public void setSalary(double salary) {
if (salary >= 0) {
this.salary = salary;
} else {
System.out.println("Salary cannot be negative");
}
}
public double getSalary() {
return salary;
}
}
class Main {
public static void main(String[] args) {
Employee e1 = new Employee();
e1.setName("Ravi");
e1.setSalary(30000);
System.out.println("Name: " + e1.getName());
System.out.println("Salary: " + e1.getSalary());
e1.setSalary(-5000);
}
}
Name: Ravi
Salary: 30000.0
Salary cannot be negative
This example uses private fields, public getters,
public setters, and validation rules.
String.isBlank() is available in Java 11
and later.
class BankAccount {
private double balance;
public BankAccount(double initialBalance) {
if (initialBalance >= 0) {
balance = initialBalance;
} else {
throw new IllegalArgumentException(
"Initial balance cannot be negative"
);
}
}
public double getBalance() {
return balance;
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
} else {
System.out.println("Invalid deposit amount");
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
} else {
System.out.println("Invalid withdrawal amount");
}
}
}
class Main {
public static void main(String[] args) {
BankAccount account = new BankAccount(1000);
account.deposit(500);
account.withdraw(200);
System.out.println(
"Balance: " + account.getBalance()
);
}
}
Balance: 1300.0
The balance is private. Deposits and withdrawals are performed through methods that validate amounts.
| Modifier | Accessibility |
|---|---|
private |
Within the declaring class |
| No modifier (package-private) | Within the same package |
protected |
Within the same package and, subject to Java's inheritance access rules, in subclasses |
public |
Accessible wherever the declaring type and its members are accessible |
Encapsulation does not automatically make a program secure. The methods exposed by a class must also be designed with appropriate validation and access control.
| Encapsulation | Abstraction |
|---|---|
| Controls access to an object's internal state. | Hides implementation details and exposes essential behavior. |
| Often uses private fields and public methods. | Often uses interfaces and abstract classes. |
| Example: A private bank balance with deposit and withdraw methods. | Example: A Payment interface with a pay method. |
1. What is encapsulation?
2. Which access modifier commonly protects fields in an encapsulated class?
3. What is the main purpose of a setter method?