Home » Encapsulation in Java

Encapsulation in Java

Encapsulation in Java

Introduction

Encapsulation is one of the fundamental concept in object-oriented programming (OOP). 

Encapsulation describes bundling data and methods that work on that data within one unit, like a class. We often often use this concept to hide an object’s internal representation or state from the outside. This is called information hiding.

The general idea of this mechanism is simple. For example, you have an attribute that is not visible from the outside of an object. You bundle it with methods that provide read or write access. Encapsulation allows you to hide specific information and control access to the object’s internal state.

If you’re familiar with any object-oriented programming language, you probably know these methods as getter and setter methods. As the names indicate, a getter method retrieves an attribute and a setter method changes it. Depending on the methods that you implement, you can decide if an attribute can be read and changed. You may also control if the attribute is read-only or not visible at all. Later, we’ll show you how you can also use the setter method to implement additional validation rules to ensure that your object always has a valid state.

Data Encapsulation can be defined as wrapping the code or methods(properties) and the related fields or variables together as a single unit. In object-oriented programming, we call this single unit – a class, interface, etc. We can visualize it like a medical capsule (as the name suggests, too), wherein the enclosed medicine can be compared to fields and methods of a class.

data-encapsulation.png

Setter and Getter Method

Getter and setter methods are used to access and modify the private variables (fields) of a class, respectively. They help achieve encapsulation by providing controlled access to the class’s attributes.

Example

public class Person {
    private String name;
    private int age;

    // Getter for name
    public String getName() {
        return name;
    }

    // Setter for name
    public void setName(String name) {
        this.name = name;
    }

    // Getter for age
    public int getAge() {
        return age;
    }

    // Setter for age
    public void setAge(int age) {
        this.age = age;
    }
}
public class Main {
    public static void main(String[] args) {
        Person person = new Person();

        // Set values using setter methods
        person.setName("John");
        person.setAge(30);

        // Retrieve values using getter methods
        System.out.println("Name: " + person.getName());
        System.out.println("Age: " + person.getAge());
    }
}
Java

Output

Name: John
Age: 30
Java
  • The main() method creates an instance of the Person class named person.
  • The setter methods setName("John") and setAge(30) are used to set the values of the name and age attributes of the person object.
  • The getter methods getName() and getAge() are used to retrieve the values of the name and age attributes, respectively.
  • The retrieved values are then printed to the console.

Implementation of Encapsulation

Example

public class Person {
    private String name;
    private int age;

    // Constructor
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter for name
    public String getName() {
        return name;
    }

    // Setter for name
    public void setName(String name) {
        this.name = name;
    }

    // Getter for age
    public int getAge() {
        return age;
    }

    // Setter for age
    public void setAge(int age) {
        if (age >= 0) {
            this.age = age;
        } else {
            System.out.println("Age cannot be negative.");
        }
    }

    // Method to display person details
    public void display() {
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
    }
}
public class Main {
    public static void main(String[] args) {
        Person person = new Person("John", 30);
        
        // Display initial details
        person.display();
        
        // Update name
        person.setName("Alice");
        
        // Update age
        person.setAge(25);
        
        // Display updated details
        person.display();
    }
}
Java

Output

Name: John
Age: 30
Name: Alice
Age: 25
Java
  • name and age are private instance variables, accessible only within the Person class.
  • getName() and setName() methods provide access to the name variable, ensuring encapsulation by controlling how the name can be accessed and modified.
  • getAge() and setAge() methods provide access to the age variable, with additional validation to ensure the age is non-negative.
  • display() method allows displaying the person’s details without exposing the internal implementation.

Data Hiding

Data hiding, also known as information hiding, is a fundamental principle of object-oriented programming and encapsulation . It refers to the concept of hiding the implementation details of a class’s attributes (data) and exposing only the necessary information or interfaces to interact with those attributes.

Data hiding is achieved by declaring class attributes as private, meaning they are accessible only within the class itself. Outside classes cannot directly access or modify these private attributes. Instead, interactions with these attributes are typically mediated through public methods such as getters and setters, which provide controlled access to the data.

Here’s how data hiding works in encapsulation:

  • Private Attributes: Attributes of a class are declared as private to restrict direct access from outside the class.
public class Person {
    private String name; // private attribute
    private int age;     // private attribute
    // other code...
}
Java
  • Public Methods: Public methods, such as getters and setters, are provided to access and modify the private attributes.
public class Person {
    private String name;
    private int age;
    
    // Getter for name
    public String getName() {
        return name;
    }
    
    // Setter for name
    public void setName(String name) {
        this.name = name;
    }

    // Getter for age
    public int getAge() {
        return age;
    }

    // Setter for age
    public void setAge(int age) {
        this.age = age;
    }
    // other code...
}
Java
  • Controlled Access: Outside classes interact with the object’s attributes only through these public methods. This way, the internal representation of data is hidden, and the class can enforce its own rules and validations.
public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        
        // Access and modify attributes via public methods
        person.setName("John");
        person.setAge(30);
        
        // Retrieve attribute values
        String name = person.getName();
        int age = person.getAge();
        
        // Display information
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
    }
}
Java

By hiding the internal implementation details and exposing only a well-defined interface, data hiding enhances encapsulation, promotes code maintainability, and reduces the risk of unintended data corruption or manipulation.

Advantages of Encapsulation

Encapsulation offers several advantages, which can be summarized in bullet points:

  • Data Hiding: Encapsulation hides the internal state of objects by making fields private, preventing direct access from outside the class.
  • Enhanced Security: With encapsulation, sensitive data can be protected from unauthorized access and modification, enhancing security.
  • Modularity and Maintainability: Encapsulation promotes modularity by isolating the implementation details within a class, making it easier to understand, maintain, and modify the codebase.
  • Code Reusability: Encapsulation encourages code reuse by allowing classes to be used as components in larger systems without exposing their internal workings.
  • Easier Testing: Encapsulation facilitates unit testing by providing clear boundaries between different components of the system, allowing for easier isolation and testing of individual units.
  • Flexibility and Evolution: Encapsulation provides flexibility in changing the internal implementation of a class without affecting its external interface, enabling the evolution of the codebase over time.
  • Reduced Coupling: Encapsulation reduces coupling between different parts of the system by limiting dependencies on the internal implementation of classes, promoting a more loosely coupled architecture.
  • Encapsulation of Invariants: Encapsulation allows the encapsulation of invariants and business rules within a class, ensuring that data remains consistent and valid throughout its lifecycle.
  • Facilitates Abstraction: Encapsulation facilitates abstraction by exposing only essential information through well-defined interfaces, hiding unnecessary details and complexity from the users of the class.
  • Supports Information Hiding: Encapsulation supports the principle of information hiding, enabling classes to hide their internal implementation details while providing a clear and consistent interface to interact with.

Conclusion

Encapsulation is a fundamental concept in object-oriented programming that promotes the bundling of data and methods within a class while restricting access to the internal state of objects. By hiding implementation details and providing controlled access through well-defined interfaces, encapsulation enhances security, modularity, maintainability, and code reuse, while also facilitating flexibility, abstraction, and reduced coupling. Overall, encapsulation fosters the creation of robust, modular, and maintainable software systems.

Frequently Asked Questions

What is encapsulation ?

Encapsulation is a mechanism of bundling the data (attributes) and methods (behaviors) that operate on the data within a single unit, i.e., a class. It involves hiding the internal state of an object and controlling access to it through public methods.

How is encapsulation achieved ?

Encapsulation is achieved by declaring class attributes as private and providing public methods (getters and setters) to access and modify these attributes. This way, the internal state of an object is hidden from outside classes, and access to it is controlled.

When should encapsulation be used ?

Encapsulation should be used whenever you want to hide the internal state of an object and provide controlled access to it. It is particularly useful when designing classes that are part of a larger system, as it helps in managing complexity, improving code maintainability, and ensuring data integrity.

Can encapsulation be bypassed ?

While encapsulation can be enforced by making attributes private and providing controlled access through methods, it is still possible to bypass encapsulation using reflection. However, doing so is generally considered bad practice and should be avoided unless absolutely necessary for specific use cases.

What are the potential drawbacks of encapsulation ?

One potential drawback of encapsulation is the overhead of creating getter and setter methods for every attribute, which can lead to increased verbosity in the code. Additionally, excessive use of encapsulation can sometimes result in overly complex class designs, making the code harder to understand and maintain.