Encapsulation & Access Modifiers in Java

Encapsulation & Access Modifiers in Java

On Day 12, we will dive into the concept of Encapsulation, another core principle of Object-Oriented Programming (OOPs) in Java. Encapsulation focuses on binding the data (fields) and methods (functions) that manipulate the data within a class. Additionally, we will cover Access Modifiers, which play a crucial role in controlling access to the members (fields and methods) of a class.


1. What is Encapsulation?

Encapsulation refers to the bundling of data (variables) and the methods (functions) that operate on that data within a single unit or class. It also restricts direct access to some of the object’s components, protecting the integrity of the data. In simpler terms, encapsulation hides the internal implementation details from the outside world and only exposes a controlled interface.

  • Encapsulation is achieved by:

    • Declaring fields as private.

    • Providing public getter and setter methods to access and modify the data indirectly.

This promotes data security and prevents unintended modifications to the internal state of an object.


2. How Encapsulation Works in Java?

In Java, you achieve encapsulation by:

  1. Declaring the fields (data members) of a class as private.

  2. Providing public getter and setter methods to control the access and update of these fields.

Example of Encapsulation:

// Encapsulated class
class Employee {
    // Private fields
    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) {
        if (age > 18) {  // Adding validation
            this.age = age;
        } else {
            System.out.println("Age should be greater than 18.");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // Creating an object of the Employee class
        Employee emp = new Employee();

        // Using setter methods to set values
        emp.setName("John Doe");
        emp.setAge(25);

        // Using getter methods to access values
        System.out.println("Employee Name: " + emp.getName());
        System.out.println("Employee Age: " + emp.getAge());
    }
}

Explanation:

  • The Employee class encapsulates the name and age fields by declaring them private.

  • The class provides public getter and setter methods to read and modify the values of these fields.

  • This approach ensures that you can control how the fields are accessed and modified, adding validation or logic within the setter method.


3. Advantages of Encapsulation:

  1. Control over Data: By using encapsulation, you can control how the data is accessed or modified. You can add validation logic in setter methods to ensure the integrity of the data.

  2. Improved Security: By hiding the internal details of an object and exposing only necessary methods, encapsulation enhances security. External classes cannot directly modify the internal state of an object.

  3. Flexibility: You can modify the internal implementation without affecting the external code that uses your class. This is because the internal details are hidden, and only the public methods are exposed.

  4. Easy Maintenance: Since encapsulation allows you to change the internal code without affecting other classes, it simplifies maintenance.


4. Access Modifiers in Java

Access Modifiers in Java define the scope and visibility of fields, methods, constructors, and classes. They control how accessible a class or class member is to other classes and packages. There are four types of access modifiers in Java:

ModifierClassPackageSubclassWorld
privateYNNN
defaultYYNN
protectedYYYN
publicYYYY

A. Private Access Modifier

  • Fields, methods, or constructors declared as private can only be accessed within the class in which they are declared.

  • Private members cannot be accessed or inherited by any subclass or outside class.

Example:
class Employee {
    private String name;  // Private field

    private void display() {  // Private method
        System.out.println("This is a private method.");
    }

    public String getName() {  // Public getter for private field
        return name;
    }

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

public class Main {
    public static void main(String[] args) {
        Employee emp = new Employee();
        emp.setName("John");  // Setter can be used to set the private field value
        System.out.println(emp.getName());  // Getter can be used to get the private field value
    }
}

B. Default (No Modifier)

  • If no access modifier is specified, Java uses default access.

  • Fields, methods, or constructors declared with default access can only be accessed within the same package.

Example:
class Employee {
    String department;  // Default access (no modifier)
}
  • In the above example, department can be accessed by classes within the same package.

C. Protected Access Modifier

  • Protected members can be accessed within the same package and by subclasses in other packages.

  • It is used to provide a level of access between private and public.

Example:
class Employee {
    protected String position;  // Protected field

    protected void work() {  // Protected method
        System.out.println("Working in position: " + position);
    }
}

class Manager extends Employee {
    void manage() {
        work();  // Accessing protected method from parent class
    }
}

D. Public Access Modifier

  • The public modifier allows a class, method, or field to be accessed from anywhere, including other classes and packages.
Example:
public class Employee {
    public String name;  // Public field
}
  • In this example, the name field can be accessed from any other class or package.

5. Combining Encapsulation with Access Modifiers

Encapsulation and access modifiers work together to protect data and ensure controlled access. By using private fields and public getter and setter methods, you can achieve a high level of data security and integrity.

Best Practice:

  • Always make your fields private and provide public getter and setter methods.

  • Use protected access for methods that should only be available to subclasses or classes within the same package.

  • Use public access for methods and fields that need to be globally accessible.


6. Example: Full Encapsulation with Access Modifiers

class Person {
    // Private fields (encapsulation)
    private String name;
    private int age;

    // Public getter and setter methods
    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) {  // Validation
            this.age = age;
        } else {
            System.out.println("Age must be positive.");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("Alice");  // Using setter to set name
        person.setAge(30);  // Using setter to set age

        System.out.println("Name: " + person.getName());  // Using getter to access name
        System.out.println("Age: " + person.getAge());  // Using getter to access age
    }
}

In this example, the Person class encapsulates the name and age fields. These fields are private, ensuring that they cannot be accessed or modified directly from outside the class. Public methods (getName(), setName(), getAge(), and setAge()) provide controlled access to these fields.


7. Summary

By the end of Day 12, we will understand:

  1. Encapsulation: How it binds data and methods, and the importance of protecting data.

  2. Access Modifiers: How to control the visibility of fields and methods using private, default, protected, and public.

  3. The benefits of Encapsulation:

    • Data security

    • Flexibility and maintainability

  4. The practical implementation of encapsulation through access modifiers and getter/setter methods.

This will provide the foundation for writing clean, secure, and maintainable code by effectively managing the visibility and accessibility of class members. So Stay tuned!!