Java Tutorial 37 of 143
Basics
- Introduction
- Download and Install Java
- Download and Install IntelliJ IDEA, Eclipse
- Creating First Java Application in IntelliJ IDEA
- JDK vs JRE vs JVM
- Print output
- Taking Input
- Identifiers
- Keywords
- Variables
- Data Types
- Literals
- Wrapper Classes
- Operators
- Decision Making
- Loops and Jump Statements
- Project: Number Guessing Game
Methods
- Introduction
- Static Methods vs Instance Methods
- Access Modifiers
- Command Line Arguments
- Variable Arguments (Varargs)
Arrays
- Introduction
- One Dimensional Arrays
- Multidimensional Arrays
- Array Class
- Arrays Class
Strings
- Introduction
- String
- StringBuffer
- StringBuilder
- String Class Methods
- StringJoiner
- StringTokenizer
OOP & Interface
- Introduction
- Java Constructors
- Java Encapsulation
- Inheritance
- Java Polymorphism
- Java Abstraction
- Interfaces
- this Keyword
- super Keyword
- static Keyword
- final Keyword
- Access Modifiers
- Nested Classes
- Anonymous Inner Class
Collections
- Collection class
- Collection Interface
- List Interface
- ArrayList
- LinkedList
- Set Interface
- HashSet
- LinkedHashSet
- TreeSet
- Queue Interface
- PriorityQueue
- Deque
- ArrayDeque
- Map Interface in Java
- HashMap
- LinkedHashMap
- TreeMap
- Hashtable
- Iterator
- Comparable and Comparator
Exception Handling
- Introduction
- Java Exception Handling
- Java Try-Catch
- Java Finally Block
- Java throw and throws
- Java Custom Exceptions
- Java Checked vs Unchecked Exceptions
Multithreading & Concurrency
- Introduction
- Thread Class
- Runnable Interface
- Thread Life Cycle
- Thread Priority
- Synchronization
- Inter-Thread Communication
- Executor Framework
- Callable and Future
- Concurrent Collections
Java 8 Features
- Lambda Expressions
- Functional Interfaces
- Method References
- Stream API
- Optional Class
- Default and Static Methods in Interface
- Date and Time API
Advanced Java Concepts
- File Handling
- Serialization and Deserialization
- Reflection API
- Annotations
- Garbage Collection
- Memory Management
- JVM Architecture
- Class Loading
- Networking
- Regular Expressions
JDBC
- Introduction
- JDBC Driver
- JDBC Connection
- Types of Statements in JDBC
- Transactions
- ResultSet
- Metadata
- Connection Pooling
Web & Enterprise
- Servlets
- JSP
- Spring Framework
- Spring Boot
- Hibernate
- REST API Development
Practice Projects
- Project: Number Guessing Game
- Project: Banking System
- Project: Student Management System
- Project: Library Management System
- Project: Quiz Application
Quiz and Coding Practice
- Java Topic-wise Quiz
- Coding Practice Problems
- Java Basics Coding Practice Problems
- Java Exercises
Interview Questions
- Core Java Interview Questions and Answers
- Advanced Java Interview Questions and Answers
- Java Interview Questions
DSA & Competitive Programming
- Arrays and Strings
- Linked List
- Stack
- Queue
- Tree
- Graph
- Heap
- Hashing
- Sorting
- Searching
- Dynamic Programming
- Roadmap for DSA in Java
Java Encapsulation
Learn Java encapsulation, how to protect object data using access modifiers, getters and setters, and why encapsulation improves code security and maintainability.
On this page
- What Is Encapsulation in Java?
- How to Achieve Encapsulation
- 1. Declare Variables as private
- 2. Provide Public Methods
- 3. Add Validation When Required
- Getters and Setters
- Why Are Variables Usually Private?
- Example of Encapsulation
- Encapsulation Using Validation
- Encapsulation and Access Modifiers
- Encapsulation Does Not Require Both Getter and Setter
- Read-Only Encapsulation
- Write-Only Encapsulation
- Encapsulation with Methods Instead of Setters
- Encapsulation vs Abstraction
- Encapsulation vs Data Hiding
- Advantages of Encapsulation
- 1. Protects Object State
- 2. Provides Controlled Access
- 3. Allows Validation
- 4. Improves Maintainability
- 5. Reduces Coupling
- 6. Improves Flexibility
- Real-World Example
- Common Mistakes
- Making All Fields Public
- Creating Setters Without Validation
- Creating Unnecessary Setters
- Key Points to Remember
- Conclusion
Java Encapsulation
Encapsulation is one of the fundamental concepts of object-oriented programming (OOP) in Java. It means bundling data and the methods that operate on that data inside a class while controlling how the data can be accessed.
In Java, encapsulation is commonly implemented by:
- Declaring instance variables as
private - Providing
publicmethods to access or modify those variables - Using validation inside methods before changing an object's state
For example:
class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 0) {
this.age = age;
}
}
}
Here, name and age cannot be accessed directly from outside the class. They are controlled through methods such as getName(), setName(), getAge(), and setAge().
What Is Encapsulation in Java?
Encapsulation is the practice of restricting direct access to an object's internal data and providing controlled access through methods.
Consider a bank account:
class BankAccount {
private double balance;
public double getBalance() {
return balance;
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
}
The balance variable is private, so external code cannot directly modify it.
Instead of allowing:
account.balance = -5000;
the class controls changes through:
account.deposit(5000);
This allows the class to enforce rules about how its data can be changed.
How to Achieve Encapsulation
Encapsulation is generally achieved using three steps.
1. Declare Variables as private
Private variables cannot be directly accessed from outside the class.
class Employee {
private String name;
private double salary;
}
2. Provide Public Methods
Public methods provide controlled access to the private data.
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
3. Add Validation When Required
Methods can validate values before changing the object's state.
public void setSalary(double salary) {
if (salary >= 0) {
this.salary = salary;
}
}
This prevents invalid values from being assigned.
Getters and Setters
Getters and setters are commonly used with encapsulated fields.
A getter retrieves the value of a field.
A setter changes the value of a field.
Example:
class Employee {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 18) {
this.age = age;
}
}
}
Usage:
Employee employee = new Employee();
employee.setName("Rahul");
employee.setAge(25);
System.out.println(employee.getName());
System.out.println(employee.getAge());
Output:
Rahul
25
Why Are Variables Usually Private?
If variables are public, any code can modify them directly.
For example:
class BankAccount {
public double balance;
}
External code could do:
BankAccount account = new BankAccount();
account.balance = -10000;
There is no control over whether the value is valid.
With encapsulation:
class BankAccount {
private double balance;
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
}
the class controls how the balance changes.
This protects the object's state from uncontrolled modifications.
Example of Encapsulation
Consider an employee class:
class Employee {
private String name;
private double salary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
if (salary >= 0) {
this.salary = salary;
}
}
}
Using the class:
public class Main {
public static void main(String[] args) {
Employee employee = new Employee();
employee.setName("Amit");
employee.setSalary(50000);
System.out.println(employee.getName());
System.out.println(employee.getSalary());
}
}
Output:
Amit
50000.0
The class controls access to its internal state.
Encapsulation Using Validation
One of the major advantages of encapsulation is that validation can be performed before modifying data.
For example:
class Account {
private double balance;
public void setBalance(double balance) {
if (balance >= 0) {
this.balance = balance;
} else {
System.out.println("Balance cannot be negative");
}
}
public double getBalance() {
return balance;
}
}
Now:
Account account = new Account();
account.setBalance(10000);
account.setBalance(-5000);
The second operation is rejected.
This is much safer than exposing the field directly.
Encapsulation and Access Modifiers
Java provides four main access levels:
| Modifier | Same Class | Same Package | Subclass | Other Packages |
|---|---|---|---|---|
private |
Yes | No | No | No |
| Default | Yes | Yes | Package-dependent access | No |
protected |
Yes | Yes | Yes, subject to inheritance/package rules | Limited |
public |
Yes | Yes | Yes | Yes |
The private modifier is especially important for encapsulation because it prevents direct external access to fields.
Example:
class Student {
private int marks;
}
The following is not allowed from outside the class:
Student student = new Student();
student.marks = 90;
Instead, a method can provide controlled access:
public void setMarks(int marks) {
if (marks >= 0 && marks <= 100) {
this.marks = marks;
}
}
Encapsulation Does Not Require Both Getter and Setter
A common misconception is that every private field must have both a getter and a setter.
That is not necessary.
You should expose only the operations that the class actually needs.
For example, an employee's ID might be assigned when the object is created and should not change later:
class Employee {
private final int id;
Employee(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
There is no setter for id.
This creates a read-only property from the caller's perspective.
Read-Only Encapsulation
A private field can be exposed through a getter without providing a setter.
class Product {
private final String productId;
Product(String productId) {
this.productId = productId;
}
public String getProductId() {
return productId;
}
}
The value can be read:
System.out.println(product.getProductId());
but cannot be changed through a setter.
Write-Only Encapsulation
A class can also provide a setter without a getter when the value should be accepted but not exposed.
For example:
class PasswordManager {
private String password;
public void setPassword(String password) {
this.password = password;
}
}
There is no method that returns the password.
In real applications, sensitive information should also be handled using appropriate security practices; simply making a field private is not a complete security mechanism.
Encapsulation with Methods Instead of Setters
Encapsulation does not always mean creating getters and setters for every field.
Sometimes a class should expose meaningful operations instead.
For example:
class BankAccount {
private double balance;
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
}
}
public double getBalance() {
return balance;
}
}
This is often better than exposing a generic setBalance() method because the class controls the valid operations that can change the balance.
Encapsulation vs Abstraction
Encapsulation and abstraction are related but represent different ideas.
| Encapsulation | Abstraction |
|---|---|
| Controls access to internal data and behavior | Hides implementation details |
| Protects object state | Focuses on essential functionality |
| Commonly uses classes and access modifiers | Commonly uses abstract classes and interfaces |
| Answers how data is accessed and controlled | Answers what functionality is exposed |
For example, a bank account can encapsulate its balance by making it private and exposing controlled methods.
At the same time, the banking system can provide an abstract withdraw() operation without exposing the internal transaction processing.
Encapsulation vs Data Hiding
The terms are closely related but are not exactly identical.
Data hiding focuses on preventing direct access to internal data.
Encapsulation is broader. It combines data and related behavior within a class and controls how that state is accessed or changed.
For example:
class Student {
private int marks;
public void setMarks(int marks) {
if (marks >= 0 && marks <= 100) {
this.marks = marks;
}
}
public int getMarks() {
return marks;
}
}
The private field provides data hiding, while the class and its methods provide encapsulation around the student's marks.
Advantages of Encapsulation
1. Protects Object State
Private fields prevent direct modification from outside the class.
2. Provides Controlled Access
Methods determine how data can be read or changed.
3. Allows Validation
Input can be validated before changing an object's state.
4. Improves Maintainability
Internal implementation can change without necessarily changing the code that uses the class.
For example, a getter can initially return a field directly:
public double getSalary() {
return salary;
}
Later, the implementation can change:
public double getSalary() {
return salary + bonus;
}
Code using getSalary() does not necessarily need to change.
5. Reduces Coupling
Other classes interact with a defined interface rather than depending directly on internal fields.
6. Improves Flexibility
A class can control which properties are readable, writable, or immutable.
Real-World Example
Consider a bank account.
A simple implementation might look like:
class BankAccount {
private double balance;
public BankAccount(double initialBalance) {
if (initialBalance >= 0) {
balance = initialBalance;
}
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
public boolean withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return true;
}
return false;
}
public double getBalance() {
return balance;
}
}
Usage:
public class Main {
public static void main(String[] args) {
BankAccount account = new BankAccount(10000);
account.deposit(5000);
boolean successful = account.withdraw(3000);
System.out.println("Withdrawal successful: " + successful);
System.out.println("Balance: " + account.getBalance());
}
}
Output:
Withdrawal successful: true
Balance: 12000.0
The balance cannot be directly modified by external code. All changes must go through the operations provided by BankAccount.
Common Mistakes
Making All Fields Public
Avoid unnecessarily exposing internal fields:
class Student {
public String name;
public int marks;
}
Prefer controlled access:
class Student {
private String name;
private int marks;
public String getName() {
return name;
}
public int getMarks() {
return marks;
}
}
Creating Setters Without Validation
This:
public void setAge(int age) {
this.age = age;
}
may allow invalid values.
If the class has rules for valid ages, enforce them:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
}
}
Creating Unnecessary Setters
Do not automatically create setters for every field.
If a value should not change after construction, make it immutable where appropriate:
private final int id;
and expose only a getter.
Key Points to Remember
- Encapsulation bundles data and related behavior inside a class.
- Private fields prevent direct external access.
- Getters provide controlled read access.
- Setters provide controlled write access.
- Getters and setters are optional; expose only the operations the class needs.
- Validation can be implemented inside methods that modify object state.
- Encapsulation can provide read-only or controlled-write properties.
privateis the most restrictive standard access modifier.- Encapsulation improves maintainability and reduces unnecessary coupling.
- Encapsulation and abstraction are related but solve different problems.
Conclusion
Encapsulation in Java protects an object's internal state by controlling how other parts of the program access and modify it. By combining private fields with carefully designed methods, a class can enforce rules, validate data, and hide implementation details.
Good encapsulation is not simply about creating getters and setters for every field. It is about exposing a clear and controlled interface while keeping the object's internal state protected.
Related
-
Java Constructors
Learn Java constructors, including default and parameterized constructors, constructor overloading, chaining, and how constructors initialize objects.
-
Inheritance
Learn Java inheritance, including single, multilevel, and hierarchical inheritance, method overriding, super, and how inheritance supports code reuse and polymorphism.
-
Java Polymorphism
Learn Java polymorphism, including compile-time and runtime polymorphism, method overloading, method overriding, dynamic method dispatch, and practical examples.
-
Java Abstraction
Learn Java abstraction using abstract classes and interfaces to hide implementation details, define common behavior, and build flexible object-oriented applications.