Skip to content

Encapsulation

In Object-oriented programming, encapsulation is a programming technique that ensures Object data integrity and simplifies programming complexity for the consumer programmer.

In this code note, we will cover following topics:

  • What is Encapsulation
  • Access Modifiers
  • Getter & Setter Methods
  • Summary



› What is Encapsulation

Encapsulation is part of the Object-oriented programming techniques for ensuring Object state integrity. Encapsulation is heavily practiced by the Class designer, who works hard to ensure that the Object created from their Class does not result in data corruption and is very simple to use.

Perspective:   Class Designer

Class designer strives to create a Data Type by creating and designing a Class. They are responsible for ensuring that the Object created from their Class is simple to use and free of data corruption caused by misuse.

Encapsulation Definition

The internal representations of an object created by a Class are generally hidden to preserve the integrity of the Object's state. This concept is known as encapsulation, and Java uses access modifiers to achieve encapsulation.

We are benefiting from encapsulation in our daily life. For example, the cell phone you are using utilizes encapsulation to prevent the user from breaking its inner components and simplifies its usage by hiding the internals of the cell phone.



› Access Modifiers

It is a set of Java keywords that limit the accessibility of fields, methods, and other Class components.

Access Modifier Same Class Same Code Package Subclass Other Packages
public visible visible visible visible
protected visible visible visible hidden
private visible hidden hidden hidden

Please watch and review following video for more comprehensive explanations:

Access Modifier Explained

Consider this poorly designed class Employee.java, where all of its fields and methods have public access modifiers:

Employee.java
public class Employee {
    // ---- Fields ----//
    public String  name;
    public double  salary;
    public long    employeeId;

    // ---- Constructors ----//
    public Employee(String n, double s) {
        name = n;
        salary = s;
        employeeId = getNextValidEmployeeId();
    }

    // --- Methods ----//
    public void promote(double amount) {
        System.out.println("Good peformeances, promoting...");
        salary += amount;
    }

    public int getNextValidEmployeeId(){
        Connection connection = EmployeeIdDatabase.getConnection();
        return connection.getId();
    }
}

Let's use the above Class to represent an actual employee by creating an Object.

Employee nijat = new Employee("Nijat Muhtar", 78000);

With the existing Employee.java class design, we can mutate the above Object's state as follows:

1
2
3
nijat.salary = -89009;                 // let's us do this...lol 
nijat.employeeId = 34324324132;        // let's us do this...omg 
int nextId = getNextValidEmployeeId(); // allows us to peek the next valid employee id

As you can see from the code segment, the Object lets us directly modify the employee's salary and their employeeId, and worst of all, it allows us to get the next possible valid employee ID from the company's secret database. Not to mention, probably the Class user is confused as to why they can use this getNextValidEmployeeId().

It stems from the misuse of access modifiers, where the Class designer should have used private modifiers instead of public modifiers. Let's fix this class by practicing Encapsulation.

Fixed Employee.java
public class Employee {
    // ---- Fields ----//
    private String  name;
    private double  salary;
    private long    employeeId;

    // ---- Constructors ----//
    public Employee(String n, double s) {
        name = n;
        salary = s;
        employeeId = getNextValidEmployeeId();
    }

    // --- Methods ----//
    // setter 
    public void updateSalary(double newAmount) {
        if(newAmount <= 0) {
            throw new Exceptions("New salary ammount cannot be negative.");
        }
        salary = newAmount
    }

    // getter 
    public String getEmployeeId(){
        String id = String.valueOf(employeeId);
        return id.subString(4);
    }

    public void promote(double amount) {
        System.out.println("Good peformeances, promoting...");
        salary += amount;
    }

    // helper method
    private int getNextValidEmployeeId(){
        Connection connection = EmployeeIdDatabase.getConnection();
        return connection.getId();
    }
}

We made the following changes to this class to fix the bad class design:

Changes
  • All the field variables are private.
  • Provided a method to allow vetted updates on the private salary fields. This method is called a Setter.
  • Provided a method to enable restricted retrieval of the value of private employeeId fields. This method is called Getter.
  • Changed access modifier of getNextValidEmployeeId() to private so that class users cannot use this method as they have no interest in this method.

Users of this Class can only see public methods that get the job done—fewer things to see and less complexity for them.

Also, our new Object created from this class won't allow any object state corruption and will only allow the user to use the method they should be using.

Usage of this Class now prevents misuse and ensures that the Object's state is always preserved. It is also simpler to use since internal helper methods are hidden from the user.

Employee nijat = new Employee("Nijat Muhtar", 78000);

nijat.salary = -89009;                // ERROR! this is no longer possible..great!!
nijat.updateSalary(-89009);           // ERROR! this will be rejected...great!!
nijat.updateSalary(89009);            // The input value is vetted...great!! 

nijat.employeeId = 34324324132;       // ERROR! this is no longer possible..great!!
System.out.println(nijat.employeeId); // ERROR! this is not possible! 
nijat.getEmployeeId();                // Only returns last 4 digits of employee id

int nextId = getNextValidEmployeeId();// ERROR! this is no longer possible, very secure!



› Getter and Setter methods

When we disable the access to the Class fields, it disables the direct access. This will prevent Class users from doing the following:

  • Directly getting the value of the field variable
  • Directly setting the value for the field variable

The purpose of disabling the direct access was to prevent Object state mutation by mistakes. However, this will create a blocker for the careful Class users whom they want to update and get the field variables content.

Therefore, we must provide a mechanism for class users to access and update the field variables in a proper way. We can do this by providing Getter & Setter methods in the class.

Getter Method:

Also called Accessor method, it allows Class user to retrieve encapsulated field variable content.

1
2
3
4
5
6
// Getter 
// returns String data from the field variable
public String getEmployeeId(){
    String id = String.valueOf(employeeId);
    return id.subString(4);
}

Make sure to mark all the field variables with private access modifiers. It achieves field encapsulation, where it prohibits direct access to the field variables. Therefore, a class designer must provide a getter method to let the user retrieve data if required or provide no getter methods if the field data should remain hidden.

Setter Method:

Also called Mutator method, it allows Class user to update the encapsulated field variable content.

1
2
3
4
5
6
7
8
// Setter
// sets the double data to the field variable 
public void updateSalary(double newAmount) {
    if(newAmount <= 0) {  // vetting the value in newAmount parameter
        throw new IllegalArgumentException("New salary ammount cannot be negative.");
    }
    salary = newAmount
}

The Class designer can provide a setter method to let the user update the private field variable content, and inside this setter method, we can write code to vet the new date values for the private fields.

If it's not allowed to update the data value of the private fields, the class designer can simply choose not to provide any setter method for the private fields.

Please watch this video to see other explanations of Encapsulation

Encapsulation Explained