Access specifiers (or access modifiers) in Java determine the visibility or accessibility of classes, methods, variables, and constructors. They help control how and where these members can be accessed within and across different classes or packages.
Types of Access Specifiers
Java has four main access specifiers:
Modifier | Class | Package | Subclass (Different Package) | World (Everywhere) |
public | Yes | Yes | Yes | Yes |
protected | Yes | Yes | Yes | No |
No Modifier (Default) | Yes | Yes | No | No |
private | Yes | No | No | No |
1. public Access Specifier
- Members declared as public are accessible everywhere in the application.
- Suitable for methods, variables, or classes that need to be universally accessible.
Example
public class PublicExample {
public void showMessage() {
System.out.println(“This is a public method.”);
}
}
// Accessible from another class
public class Main {
public static void main(String[] args) {
PublicExample obj = new PublicExample();
obj.showMessage(); // Works fine
}
}
2. protected Access Specifier
- Members declared as protected are accessible:
- Within the same package.
- In subclasses, even if they are in different packages.
Example
// Package: mypackage
package mypackage;
public class ProtectedExample {
protected void showMessage() {
System.out.println(“This is a protected method.”);
}
}
// Another class in the same package
package mypackage;
public class Main {
public static void main(String[] args) {
ProtectedExample obj = new ProtectedExample();
obj.showMessage(); // Works fine
}
}
// Subclass in a different package
package otherpackage;
import mypackage.ProtectedExample;
public class SubClass extends ProtectedExample {
public static void main(String[] args) {
SubClass obj = new SubClass();
obj.showMessage(); // Works fine
}
}
3. Default (No Modifier)
- If no access specifier is provided, the default access level is used.
- Members are accessible only within the same package.
- Often used when access should be restricted to a specific package.
Example
// Default access
class DefaultExample {
void showMessage() {
System.out.println(“This is a default method.”);
}
}
// Accessible in the same package
class Main {
public static void main(String[] args) {
DefaultExample obj = new DefaultExample();
obj.showMessage(); // Works fine
}
}
- Not Accessible in a Different Package:
import mypackage.DefaultExample; // Compilation error
4. private Access Specifier
- Members declared as private are accessible only within the class in which they are defined.
- Used for encapsulation, to restrict access to class members.
Example
public class PrivateExample {
private void showMessage() {
System.out.println(“This is a private method.”);
}
public void accessPrivateMethod() {
showMessage(); // Accessible within the same class
}
}
public class Main {
public static void main(String[] args) {
PrivateExample obj = new PrivateExample();
// obj.showMessage(); // Compilation error
obj.accessPrivateMethod(); // Works fine
}
}
Encapsulation with Access Specifiers
Encapsulation is often achieved by making fields private and providing public getter and setter methods for controlled access.
Example
public class EncapsulationExample {
private String name;
// Getter
public String getName() {
return name;
}
// Setter
public void setName(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
EncapsulationExample obj = new EncapsulationExample();
obj.setName(“John”);
System.out.println(obj.getName()); // Outputs: John
}
}
Use Cases of Access Specifiers
Access Specifier | Use Case |
public | Use for methods or variables that should be universally accessible (e.g., API endpoints). |
protected | Use for methods or variables that should be available to subclasses but not the entire app. |
Default | Use when members should be accessible only within the same package. |
private | Use to restrict access to the implementation details of a class. |
Best Practices
- Default to Private:
- Start with private for fields and methods unless wider access is required.
- Minimize public Usage:
- Only use public when necessary for external access.
- Use protected for Inheritance:
- Make members protected if they are designed for subclass extension.
- Avoid Package Dependency:
- Don’t rely heavily on default access unless you have strict package boundaries.
By properly using access specifiers, you can enhance encapsulation, maintainability, and security in your Java applications.