Encapsulation in Java With Examples

What is Encapsulation?

The process of wrapping up data and code in a single unit is known as encapsulation. The process involves binding data inside the code, and this code is the one capable to manipulate it.

In real life, we see capsules, which contain fine granules and a protective shield around it. This layer restricts the alien particle to access the granules. So the granules are data and the shield is the code.

The idea is to hide data members from getting accessed directly. We can access data but only via member methods. In order to do so, we declare all our variables with access specifier as private, and all the member methods as public. So the class is accessible to all without but the implementation detail is hidden making it a combo of abstraction and data-hiding.

Why Encapsulation?

  • Data Hiding: The implementation will be completely hidden from the user. The values will be set as per the logic of methods, and the user will have no access to it. The only concern is to utilize methods effectively serving the purpose. We have getters and setters for the same.
  • Increased Flexibility: The data member can be customized according to the need. If required to make the variables as read-only, then we have to omit the setter methods like setData() in our code. Similarly, if we wish to make the variables as write-only then we have to omit getter methods like getData();
  • Reusability: Encapsulation makes our code scalable to change it as per our requirement.

Let us see few examples to get the essence of encapsulation.

We have a class customer. It has three data members name, discount, and status. All are declared private. The getter setter methods of this class are public which contains the logic of data manipulation.

class Customer {
private String name;
private double discount;
private String status;

//Default Constructor
public Customer() {   
                this.name = "NA";
                this.status = "NA";       
                setDiscount(); 
}
//Parameterized Constructor
public Customer(String name, String status) {   
                this.name = name;
                this.status = status;       
                setDiscount(); 
}
//getter and setter method
public String getName(){
       return name;
}
public void setName(String name){
       this.name = name;
}
public double getDiscount(){
        return discount;
}
public String getStatus() {
       return status;
}
public void setStatus(String status) {
       this.status = status;
       setDiscount();
}

public void setDiscount(){
       if(this.status.equalsIgnoreCase("Active"))
               this.discount=5;
       else if(this.status.equalsIgnoreCase("VIP"))
               this.discount=10;
       else
               this.discount=0;
}
}

public class HelloWorld{
     public static void main(String []args){
         Customer obj = new Customer();
         obj.setName("TechieClues");
         obj.setStatus("VIP");
        System.out.println("Customer Name : "+obj.getName());
        System.out.println("Customer Status : "+obj.getStatus());
        System.out.println("Customer Discount : "+obj.getDiscount());
     }
}

Output:

Customer Name :TechieClues
Customer Status :VIP
Customer Discount :10.0

Read-Only Class

In order to convert it to a read-only class, we can simply omit the setters. That is the beauty of encapsulation, where few changes can scale class to obtain a different nature.

class Customer {
private String name;
private double discount;
private String status;

//Default Constructor
public Customer() {   
                this.name = "NA";
                this.status = "NA";       
                setDiscount(); 
}
//Parameterized Constructor
public Customer(String name, String status) {   
                this.name = name;
                this.status = status;       
                setDiscount(); 
}
//getter and setter method
public String getName(){
       return name;
}
public double getDiscount(){
        return discount;
}
public String getStatus() {
       return status;
}
private void setDiscount(){
       if(this.status.equalsIgnoreCase("Active"))
               this.discount=5;
       else if(this.status.equalsIgnoreCase("VIP"))
               this.discount=10;
       else
               this.discount=0;
}
}

public class HelloWorld{
     public static void main(String []args){
        Customer obj = new Customer("TechieClues","VIP");
        System.out.println("Customer Name : "+obj.getName());
        System.out.println("Customer Status : "+obj.getStatus());
        System.out.println("Customer Discount : "+obj.getDiscount());
     }
}

Output:

Customer Name :TechieClues
Customer Status :VIP
Customer Discount :10.0

Notice that we have a setter method kept privately. This is only for internal use and cannot be used outside. This is another aspect of hiding even the method members.

Write-Only Class

As discussed earlier,  here in the case of a write-only class, omitting the getters will suffice.

class Customer {
private String name;
private double discount;
private String status;

//Default Constructor
public Customer() {   
                this.name = "NA";
                this.status = "NA";       
                setDiscount(); 
}

//Parameterized Constructor
public Customer(String name, String status) {   
                this.name = name;
                this.status = status;       
                setDiscount(); 
}
// setter method
public void setName(String name){
       this.name = name;
}

public void setStatus(String status) {
       this.status = status;
       setDiscount();
}

public void setDiscount(){
       if(this.status.equalsIgnoreCase("Active"))
               this.discount=5;
       else if(this.status.equalsIgnoreCase("VIP"))
               this.discount=10;
       else
               this.discount=0;
}
}

public class HelloWorld{
     public static void main(String []args){
         Customer obj = new Customer();
         obj.setName("TechieClues");
         obj.setStatus("VIP");
     }
}

We simply can set value and cannot retrieve it. This kind of a class is rarely of any use, as the data we set needs to be used for processing in general.

This was an overview of Java Encapsulation. We will discuss the Exception Handling in the next lecture.