Encapsulation in Java

Encapsulation is an important part of object oriented programming. It is part of what makes OOP “safer” and more easy to use. Briefly stated Encapsulation is a concept of hiding information details and protecting data and behavior of an object.

Encapsulation and abstraction are related features in object oriented programming. Encapsulation enables a programmer to implement the desired level of abstraction.

Private No Public

Private Sign

In Java, encapsulation is done using access modifiers with classes, interfaces, setters, and getters. Java supports the following access modifiers:

  • private
  • public
  • protected
  • default

private

private access modifier allows a class to hide its member variables and member functions from other functions and objects. Only functions in the same class can access its private members. Even a subclass cannot access private members of the base class.

public

public access modifier allows a class to expose its member variables and member functions to other functions and objects. Any public member can be accessed from outside the class.

Let's check our example below.

Rectangle.java
public class Rectangle {
    
    // member variables are private, 
    // then we implement setter & getter
    private double height;
    private double width;

    /**
     * @return the height
     */
    public double getHeight() {
        return height;
    }

    /**
     * @param height the height to set
     */
    public void setHeight(double height) {
        this.height = height;
    }

    /**
     * @return the width
     */
    public double getWidth() {
        return width;
    }

    /**
     * @param width the width to set
     */
    public void setWidth(double width) {
        this.width = width;
    }
    
    public double getArea() {
        return this.height * this.width;
    }

    public void display() {
        System.out.println("Height: " + this.height);
        System.out.println("Width: " + this.width);
        System.out.println("Area: " +  getArea());
    }
}
                    

RectangleApp.java
public class RectangleApp {
    
    public static void main(String[] args) {
        Rectangle r = new Rectangle();
        r.setHeight(2.4);
        r.setWidth(4.9);
        r.display();
    }
}

/* 
Output:
------    
Height: 2.4
Width: 4.9
Area: 11.76
*/
                    

Class Rectangle has 2 private members height & weight. To access height and weight, another class must go through their setter and getter. So code below:

public static void main(String[] args) {
        Rectangle r = new Rectangle();
        r.height = 2.4;
        r.width = 4.9;
        r.display();
 }
                    

will resulting compilation error:

RectangleApp.java:[5,10] height has private access in Rectangle RectangleApp.java:[6,10] width has private access in Rectangle

The member functions getArea() and display() in Class Rectangle can access these variables. And as in the example, since the member function display() is declared public, they can be accessed from main() using an instance of the Rectangle class, named r.

protected

protected access modifier allows a subclass to access the member variables and member functions of its base class. This way it helps in implementing inheritance. Please read here for Inheritance in Java.

Let's check example codes below:

Rectangle.java
public class Rectangle {
    
    // member variables are protected
    protected double height;
    protected double width;
    
    protected double getArea() {
        return this.height * this.width;
    }
}
                    

Square.java
public class Square extends Rectangle {
    
    public String checkSquare() {
        if (this.width == this.height) {
            return "a square";
        }
        else {
            return "not a square";
        }
    }
    
    public static void main(String[] args) {
        Square s1 = new Square();
        s1.height = 10;
        s1.width = 12;
        System.out.print("s1 is " + s1.checkSquare());
        System.out.println (" with area: " + s1.getArea());
        
        Square s2 = new Square();
        s2.height = 7;
        s2.width = 7;
        System.out.print("s2 is " + s2.checkSquare());
        System.out.println (" with area: " + s2.getArea());
    }
}

/*
Output:
------  
s1 is not a square with area: 120.0
s2 is a square with area: 49.0
*/
                    

Since height and width are declared as protected in Rectangle, Square as a subclass able to access it directly without the need of helper functions like setter and getter.

default

If we never mention any access modifier above (public, private, and protected), then it becomes default. The scope of this modifier is limited to the package only. This means that if we have a class with the default access modifier in a package, only classes in the same package can access this class. Similarly, if we have a default method or data member in a class, it would not be visible in the class of another package.

Let's check example below:

Polygon.java
package com.dariawan.codes.oop;

public class Polygon {
    
    void draw() {
        System.out.println("Drawing Polygon");
    }
}
                    

What happen if we have Circle class but in different packages?

Circle.java
package com.dariawan.codes.shapes;

import com.dariawan.codes.oop.Polygon;

public class Circle extends Polygon {
    
    @Override
    public void draw() {
        System.out.println("Drawing Circle");
        super.draw();
    }
}
                    

We will encounter compilation error:

com/dariawan/codes/shapes/Circle.java:[7,5] method does not override or implement a method from a supertype com/dariawan/codes/shapes/Circle.java:[10,14] draw() is not public in com.dariawan.codes.oop.Polygon; cannot be accessed from outside package

draw() method in the Polygon class has no access modifier, which means that it is implicitly assigned the default / package access modifier. Since Circle class is in different package, it'll raise compilation error.

OK, now we know the problem, we need to correct it:

Circle.java
package com.dariawan.codes.oop;

public class Circle extends Polygon {
    
    @Override
    public void draw() {
        System.out.println("Drawing Circle");
        super.draw();
    }
}
                    

In Summary

If you cannot remember everything, just remember these summary of Java four access modifiers:

  • private - only code in the same class can access this member
  • public - any class in any package can access this member
  • protected - sub classes in any package can access this member (as well as code in the same class)
  • default - only code in the same package can access this member

And here the matrix in table mode from the most restrictive (private) to least restrictive (public):

classsame
package
subclass
(same package)
subclass
(different package)
other class
privateYNNNN
default
(no modifier)
YYYNN
protectedYYYYN
publicYYYYY