In Java, access modifiers are used to define the level of visibility or accessibility of classes, methods, variables, and constructors. The four main access modifiers are public, private, protected, and default (package-private).
Access modifiers are fundamental for controlling how different parts of a program interact. Choosing the right access modifier helps protect data, encourage proper use of inheritance, and ensure that the classes are used correctly.

Public
The public modifier grants the widest level of access. Members marked as public can be accessed from any other class, no matter the package.
- Where it can be accessed: Anywhere in the program, even in different packages.
- Use case: Typically used for methods and classes that should be globally accessible.
Example
| 1 2 3 4 5 6 7 | public class Example {     public int value = 5;     public void display() {         System.out.println("This is a public method.");     } } | 
You can access public members from any class, regardless of the package.
Private
The private modifier is the most restrictive. It restricts access to the class members to the same class only. No other class, even in the same package, can access private members.
- Where it can be accessed: Only within the same class.
- Use case: Ideal for encapsulation, where you want to hide the implementation details.
Example:
| 1 2 3 4 5 6 7 | class Example {     private int secret = 42;     private void showSecret() {         System.out.println("This is private.");     } } | 
In this case, no class outside Example can access the secret variable or the showSecret() method.
Protected
The protected modifier allows access within the same package and to subclasses, even if they are in a different package.
- Where it can be accessed: Same package and subclasses (even in different packages).
- Use case: Useful in inheritance hierarchies, where you want a subclass to have access to certain members.
Example:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package package1; public class Parent {     protected int num = 10;     protected void showNum() {         System.out.println("Number: " + num);     } } package package2; import package1.Parent; public class Child extends Parent {     public static void main(String[] args) {         Child obj = new Child();         System.out.println(obj.num); // Accessible due to inheritance         obj.showNum(); // Accessible due to inheritance     } } | 
Here, the Child class can access the protected members of the Parent class because it inherits from it.
Default (Package-Private)
If no access modifier is specified, the default modifier is applied. This allows access only within the same package.
- Where it can be accessed: Only within the same package.
- Use case: Often used for classes or methods that should be restricted to a particular package.
Example:
| 1 2 3 4 5 6 7 | class Example {     int count = 100; // Default access     void displayCount() {         System.out.println("Count: " + count);     } } | 
In this case, count and displayCount() can only be accessed within the same package.
Access Modifiers Comparison
| Modifier | Same Class | Same Package | Subclass (Different Package) | Other Packages | 
|---|---|---|---|---|
| public | ✅ | ✅ | ✅ | ✅ | 
| private | ✅ | ❌ | ❌ | ❌ | 
| protected | ✅ | ✅ | ✅ | ❌ | 
| default | ✅ | ✅ | ❌ | ❌ | 
