ZeroToSky
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

All 17 lessons →

Methods
  • Introduction
  • Static Methods vs Instance Methods
  • Access Modifiers
  • Command Line Arguments
  • Variable Arguments (Varargs)

All 5 lessons →

Arrays
  • Introduction
  • One Dimensional Arrays
  • Multidimensional Arrays
  • Array Class
  • Arrays Class

All 5 lessons →

Strings
  • Introduction
  • String
  • StringBuffer
  • StringBuilder
  • String Class Methods
  • StringJoiner
  • StringTokenizer

All 7 lessons →

OOP & Interface

All 14 lessons →

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

All 20 lessons →

Exception Handling

All 7 lessons →

Multithreading & Concurrency
  • Introduction
  • Thread Class
  • Runnable Interface
  • Thread Life Cycle
  • Thread Priority
  • Synchronization
  • Inter-Thread Communication
  • Executor Framework
  • Callable and Future
  • Concurrent Collections

All 10 lessons →

Java 8 Features
  • Lambda Expressions
  • Functional Interfaces
  • Method References
  • Stream API
  • Optional Class
  • Default and Static Methods in Interface
  • Date and Time API

All 7 lessons →

Advanced Java Concepts
  • File Handling
  • Serialization and Deserialization
  • Reflection API
  • Annotations
  • Garbage Collection
  • Memory Management
  • JVM Architecture
  • Class Loading
  • Networking
  • Regular Expressions

All 10 lessons →

JDBC
  • Introduction
  • JDBC Driver
  • JDBC Connection
  • Types of Statements in JDBC
  • Transactions
  • ResultSet
  • Metadata
  • Connection Pooling

All 8 lessons →

GUI & Desktop
  • AWT
  • Swing
  • JavaFX

All 3 lessons →

Web & Enterprise
  • Servlets
  • JSP
  • Spring Framework
  • Spring Boot
  • Hibernate
  • REST API Development

All 6 lessons →

Practice Projects
  • Project: Number Guessing Game
  • Project: Banking System
  • Project: Student Management System
  • Project: Library Management System
  • Project: Quiz Application

All 5 lessons →

Quiz and Coding Practice
  • Java Topic-wise Quiz
  • Coding Practice Problems
  • Java Basics Coding Practice Problems
  • Java Exercises

All 4 lessons →

Interview Questions
  • Core Java Interview Questions and Answers
  • Advanced Java Interview Questions and Answers
  • Java Interview Questions

All 3 lessons →

DSA & Competitive Programming
  • Arrays and Strings
  • Linked List
  • Stack
  • Queue
  • Tree
  • Graph
  • Heap
  • Hashing
  • Sorting
  • Searching
  • Dynamic Programming
  • Roadmap for DSA in Java

All 12 lessons →

Java Encapsulation

Learn Java encapsulation, how to protect object data using access modifiers, getters and setters, and why encapsulation improves code security and maintainability.

Gaurav 6 min read Sign in to save
On this page

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 public methods 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.
  • private is 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

Found a problem on this page, or something that could be clearer?

Goes straight to the author. Not published anywhere.