Last Updated: January 3, 2026
Understanding access modifiers is crucial for encapsulating your data and controlling access within your Java applications. They not only influence visibility but also help establish a solid architecture and design in your code.
Let's dive in and explore the different types of access modifiers, their use cases, and the best practices for applying them effectively.
Access modifiers in Java define the visibility or accessibility of classes, methods, and variables. They play an essential role in encapsulation, one of the core principles of object-oriented programming (OOP). By controlling access, you can protect the integrity of your objects and make your code more maintainable.
Java provides four primary access modifiers:
Each of these modifiers has distinct implications on how and where elements can be accessed in your code.
The public modifier allows a class, method, or variable to be accessible from any other class. This is the least restrictive access level. When you declare something as public, you are saying that it can be accessed from anywhere in your application.
In this example, the User class and its username variable are public. Any other class can access the username and invoke displayUsername() without any restrictions.
The protected modifier is more restrictive than public. It allows access to classes in the same package and to subclasses, even if they are in different packages. This modifier is useful for inheritance, where you want to allow subclasses to access certain properties or methods.
Here, the sound variable and makeSound() method in the Animal class are protected. The Dog class, which extends Animal, can access these members, allowing it to use the inherited functionality.
When you don't specify an access modifier, Java uses the default access level. This means the class, method, or variable is accessible only within its own package. This is useful for package-private classes that should not be exposed to the outside world.
In this code, PackagePrivateClass is accessible only within the same package. If you try to access display() from a different package, you'll get a compilation error.
The private modifier is the most restrictive access level. A private member can only be accessed within its own class. This is crucial for maintaining encapsulation, where you want to hide the internal state of an object from the outside world.
In this example, the balance variable is private. It cannot be accessed directly from outside the BankAccount class, ensuring that the balance can only be modified through the deposit method. This encapsulation prevents arbitrary changes to the balance.
You can also combine access modifiers with other keywords like static and final to fine-tune access levels in your classes. For example, you could have a public static method that is accessible from anywhere but works with private instance variables.
Here, setting is a private static variable. It's modified and accessed through public static methods, allowing controlled access to it while keeping the actual data private.
Understanding when to use each access modifier can significantly improve your code's maintainability and readability. Here are some best practices to keep in mind:
By following these best practices, you can create a robust and maintainable codebase that leverages the power of access modifiers effectively.
Now that you understand access modifiers and how they can help you encapsulate your data and control access in your Java applications, you are ready to explore the next important topic: Getters and Setters.
In the next chapter, we will look at how these methods provide a controlled interface to your class's private data, enhancing encapsulation further while also maintaining flexibility.