OOP

Java Access Modifiers Tutorial with Examples

In Java, access modifiers control the visibility and accessibility of classes, methods, and variables. They are an essential part of encapsulation, which is one of the key principles of Object-Oriented Programming (OOP).

Java provides four types of access modifiers:

  1. Private: Accessible only within the same class.
  2. Default (Package-private): Accessible only within the same package.
  3. Protected: Accessible within the same package and also in subclasses.
  4. Public: Accessible from everywhere.

In this tutorial, we will cover:

Let’s dive into each type of access modifier with examples!


1. What are Access Modifiers?

Access modifiers in Java define how the members (variables, methods, constructors) and classes themselves can be accessed. They control visibility and ensure that sensitive data or behavior is encapsulated within a class or a package.

The Four Types of Access Modifiers:

  • Private: Restricted to the same class.
  • Default (Package-private): Accessible only within the same package. (No explicit keyword is used.)
  • Protected: Accessible within the same package and by subclasses (even in different packages).
  • Public: Accessible from any other class.

2. Private Access Modifier

The private access modifier makes a member visible only within its own class. No other class can access this member, even if they are in the same package.

Example: Private Access Modifier

class PrivateExample {
    private String secretMessage = "This is private";

    private void showSecret() {
        System.out.println(secretMessage);
    }

    public void publicMethod() {
        System.out.println("Public method called.");
        showSecret();  // Private method accessed inside the class
    }
}

public class Main {
    public static void main(String[] args) {
        PrivateExample obj = new PrivateExample();
        obj.publicMethod();  // Output: Public method called. This is private.

        // Below lines will throw errors because secretMessage and showSecret() are private
        // System.out.println(obj.secretMessage);  // Error
        // obj.showSecret();  // Error
    }
}

Explanation:

  • The variable secretMessage and the method showSecret() are marked as private and can only be accessed within the PrivateExample class.
  • The publicMethod() method can call the private method because it is inside the same class.

3. Default (Package-private) Access Modifier

If no access modifier is specified, Java applies default access (also known as package-private access). Members with default access are accessible by any class within the same package but not from other packages.

Example: Default Access Modifier (Package-private)

// Inside package "mypackage"
package mypackage;

class DefaultExample {
    String defaultMessage = "This is default access";

    void showMessage() {
        System.out.println(defaultMessage);
    }
}

// Inside the same package "mypackage"
package mypackage;

public class MainInSamePackage {
    public static void main(String[] args) {
        DefaultExample obj = new DefaultExample();
        obj.showMessage();  // Output: This is default access
    }
}

// Inside a different package "otherpackage"
package otherpackage;

import mypackage.DefaultExample;

public class MainInOtherPackage {
    public static void main(String[] args) {
        DefaultExample obj = new DefaultExample();
        // obj.showMessage();  // Error: showMessage() has package-private access
    }
}

Explanation:

  • The defaultMessage variable and the showMessage() method are package-private, meaning they can only be accessed within the mypackage package.
  • Trying to access them from a class in the otherpackage package will result in an error.

4. Protected Access Modifier

The protected access modifier allows access to members within the same package and to subclasses (even if the subclasses are in a different package).

Example: Protected Access Modifier

// Inside package "mypackage"
package mypackage;

public class Animal {
    protected String sound = "Generic animal sound";

    protected void makeSound() {
        System.out.println(sound);
    }
}

// Inside a subclass in the same package "mypackage"
package mypackage;

public class Dog extends Animal {
    public void dogBark() {
        System.out.println("Dog barks");
    }

    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.makeSound();  // Output: Generic animal sound (inherited from Animal)
        dog.dogBark();    // Output: Dog barks
    }
}

// Inside a subclass in a different package "otherpackage"
package otherpackage;

import mypackage.Animal;

public class Cat extends Animal {
    public void catMeow() {
        System.out.println("Cat meows");
        System.out.println("Animal sound: " + sound);  // Accessing protected member
    }

    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.makeSound();  // Output: Generic animal sound (inherited)
        cat.catMeow();    // Output: Cat meows. Animal sound: Generic animal sound
    }
}

Explanation:

  • The sound variable and makeSound() method are declared as protected in the Animal class.
  • They are accessible in the subclass Dog in the same package and the subclass Cat in a different package (otherpackage).

5. Public Access Modifier

The public access modifier allows a class, method, or variable to be accessible from anywhere. If a member is marked as public, there are no restrictions on its visibility.

Example: Public Access Modifier

// Inside package "mypackage"
package mypackage;

public class PublicExample {
    public String message = "This is public";

    public void showMessage() {
        System.out.println(message);
    }
}

// Inside any package (even outside "mypackage")
package otherpackage;

import mypackage.PublicExample;

public class Main {
    public static void main(String[] args) {
        PublicExample obj = new PublicExample();
        obj.showMessage();  // Output: This is public
    }
}

Explanation:

  • The message variable and showMessage() method are declared as public, making them accessible from any class in any package.
  • The class PublicExample itself is also declared as public, so it can be imported and used in the otherpackage package.

6. Access Modifiers with Classes

In Java, top-level classes can only have public or default (package-private) access. A public class can be accessed from any package, while a class with default access is only accessible within the same package.

Example: Access Modifiers with Classes

// Inside package "mypackage"
package mypackage;

// Default access class (Package-private)
class DefaultClass {
    public void display() {
        System.out.println("Default access class method.");
    }
}

// Public access class
public class PublicClass {
    public void display() {
        System.out.println("Public class method.");
    }
}

// In a different package "otherpackage"
package otherpackage;

import mypackage.PublicClass;

public class Main {
    public static void main(String[] args) {
        PublicClass publicObj = new PublicClass();
        publicObj.display();  // Output: Public class method.

        // DefaultClass defaultObj = new DefaultClass();  // Error: DefaultClass is not public
    }
}

Explanation:

  • The PublicClass is declared public, so it can be accessed from anywhere.
  • The DefaultClass is package-private, so it can only be accessed within the mypackage package, and trying to access it from otherpackage results in an error.

Summary of Java Access Modifiers

Modifier Class Within Package Subclass (Different Package) Other Packages
private Same class only Not accessible Not accessible Not accessible
default Same package only Accessible Not accessible Not accessible
protected Same package + subclasses Accessible Accessible in subclass Not accessible
public Accessible everywhere Accessible everywhere Accessible everywhere Accessible everywhere

7. Examples and Use Cases

Example 1: Using protected in Inheritance

package mypackage;

public class Vehicle {
    protected int speed = 100;

    protected void showSpeed() {
        System.out.println("Speed: " + speed);
    }
}

package otherpackage;

import mypackage.Vehicle;

public class Car extends Vehicle {
    public void displaySpeed() {
        showSpeed();  // Accessing protected method
    }

    public static void main(String[] args) {
        Car car = new Car();
        car.displaySpeed();  // Output: Speed: 100
    }
}

Example 2: Restricting Access with private

class Account {
    private double balance = 5000;

    // Private method
    private void updateBalance(double amount) {
        balance += amount;
    }

    public void deposit(double amount) {
        if (amount > 0) {
            updateBalance(amount);  // Private method can be accessed inside the class
            System.out.println("Deposited " + amount);
        }
    }

    public double getBalance() {
        return balance;
    }
}

public class Main {
    public static void main(String[] args) {
        Account account = new Account();
        account.deposit(500);  // Output: Deposited 500
        System.out.println("Balance: " + account.getBalance());  // Output: Balance: 5500

        // account.updateBalance(100);  // Error: updateBalance() is private
    }
}

Conclusion

In Java, access modifiers are essential for controlling the visibility and accessibility of classes, methods, and variables. They are fundamental in implementing encapsulation, one of the four principles of Object-Oriented Programming (OOP). In this tutorial, we covered:

  • Private access for ensuring that methods and variables are only accessible within the same class.
  • Default access for restricting access to members within the same package.
  • Protected access for allowing access within the same package and to subclasses.
  • Public access for allowing unrestricted access to members.

Related posts

Java Hidden Classes

Java sealed classes

Java Static Classes