Java Encapsulation & Access Modifiers Tutorial

In this Java tutorial we learn how to use access modifiers like public, private and protected to hide and protect class members.

We also discuss how to access and mutate private or protected members with getter and setter methods.

What is encapsulation

One of the three core principles in any object oriented program is encapsulation. Encapsulation is where we hide unnecessary implemetation details from the object.

As an example, consider a class that translates a document into another language.

The class would encapsulate the inner details of loading, manipulating and closing the file. We don’t need to worry about how it loads the document behind the scenes.

All we do is instantiate the class, and send it the appropriate commands, like: Open a file from this location, save file to that location etc.

Encapsulation also provides us with data protection, we can’t accidentally change how a file is manipulated from outside the class if it’s properly protected.

How to encapsulate a class with access modifiers in Java

To encapsulate members of our class, we need to use certain access modifiers. These are keywords that specify the level of access, or protection, class members have.

The table below shows the available access modifiers:

ModifierDescription
publicNo access restriction. Can be accessed from an object or any child class
privateCan only be accessed from within the class that defines it
protectedCan only be accessed from within the class that defines it, as well as any child class
defaultCan only be accessed from within the current package

The public access modifer in Java

The public access modifier means the member can be accessed from objects, external packages and any derived classes (classes that inherit from this one).

The public modifier can be applied to classes , interfaces , methods and properties.

Syntax:
// public class
public class class_name {

    // public property
    public type property;

    // public method
    public return_type method_name() {

    }
}
Example:
public class Program {
    public static void main(String[] args) {

        Logger log1 = new Logger();

        log1.logMessage("Hello");
    }
}

class Logger {

    // public method
    public void logMessage(String msg) {
        System.out.println(msg);
    }
}

In the example above, our public method can be accessed outside of the ‘Logger’ class.

The private access modifier in Java

When the private modifier is applied to class members, they can only be accessed inside their current class.

When we create a new object, we cannot access a private member through that object. For example, if the method ‘logMessage’ is private, we can’t use object.logMessage .

Only the properties and methods of a class can be marked as private.

Syntax:
class class_name {

    // private property
    private type property;

    // private method
    private return_type method_name() {

    }
}

The private access modifier is the default modifier and doesn’t need to be specified explicitly, although it’s considered good practice to always be explicit.

Syntax:
class class_name {

    // private property
    type property;

    // private method
    return_type method_name() {

    }
}
Example:
public class Program {
    public static void main(String[] args) {

        Logger log1 = new Logger();

        log1.logMessage("Hello");
    }
}

class Logger {

    // private method
    private void logMessage(String msg) {
        System.out.println(msg);
    }
}

In the example above, we marked our method as private. When we try to compile and run the script, the compiler raises an error.

Output:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
    The method logMessage(String) from the type Logger is not visible

The protected access modifier in Java

A protected member can only be accessed by the class it’s currently in, as well as any class that inherits from it (child classes).

As with the private access modifier, only properties and methods can be marked as protected.

Syntax:
class class_name {

    // protected property
    protected type property;

    // protected method
    protected return_type method_name() {

    }
}
Example:
public class Program {
    public static void main(String[] args) {

        AccessChild log = new AccessChild();

        log.childMessage();
    }
}

class Access {

    protected String msg1 = "Protected property";
    protected String msg2 = "Access inside current and child";

    protected void parentMessage() {
        System.out.println(msg1 + " - " + msg2);
    }
}

class AccessChild extends Access {

    protected void childMessage() {
        System.out.println("Accessed from parent");
        System.out.println(msg1 + " - " + msg2);
    }
}

In the example above, we create a child class that derives from the class Access and instantiate a child class object. The child class has access to the two protected fields of its parent class.

Accessor and Mutator methods (getters and setters) in Java

Access and mutator methods allow us to protect members of a class with the private or protected modifiers, but still access them. They’re also commonly referred to as getters and setters.

As an example, let’s consider an Employee class with first and last name properties. We want to protect the name from being changed for security reasons.

But what if the employee gets married and takes a different last name. We need a way to safely change the protected property without affecting anything else.

The solution is public getter and setter methods that only perform a single task, retrieving a value, or mutating it.

Syntax:
class class_name {

    // private property
    private type property_name;

    // public getter
    public return_type getProperty() {

        return property_name;
    }

    // public setter
    public void setProperty(type new_value) {

        this.property_name = new_value;
    }
}

Getter and setter methods may have any name, but we commonly name them after the property and prefix that with the word get or set.

Example:
public class Program {
    public static void main(String[] args) {

        Employee emp1 = new Employee();

        // return private property
        // with getter method
        System.out.println("Last name: " + emp1.getLastName() );

        // mutate private property
        // with setter method
        emp1.setLastName("Watson");

        System.out.println("New last name: " + emp1.getLastName() );
    }
}

class Employee {

    private String firstName = "Jane";
    private String lastName = "Doe";

    // getter
    public String getLastName() {

        return lastName;
    }

    // setter
    public void setLastName(String newLastName) {

        this.lastName = newLastName;
    }
}

In the example above, we use the get and set methods to access and mutate the private ‘lastName’ property in the class.

Summary: Points to remember

  • Encapsulation is when we define the access level of our classes.
    • The public access modifier doesn’t impose any restrictions.
    • The private access modifier only allows members to be accessed within the current class, not outside of it (through an object).
    • The protected access modifier allows the current class, and any child classes that inherit from it, to access its members.
  • Accessor and mutator methods are used to access and modify private and protected members.