What Is an Access Modifier? Learn Java Access Modifiers
Access modifiers (also called access specifiers) define the visibility and accessibility of classes, methods, variables, and constructors in Java.
They determine who can access a particular class or member, helping enforce encapsulation, improve security, and organize code.
Java provides four access modifiers:
privatedefault(package-private)protectedpublic
Why Are Access Modifiers Important?
Access modifiers help:
- Protect sensitive data.
- Support encapsulation.
- Improve code organization.
- Prevent unauthorized access.
- Promote code reusability.
Real-Life Example
Think of your house.
- Private → Only you can enter your bedroom.
- Protected → Family members can enter.
- Default → Society members can enter your apartment building.
- Public → Anyone can enter a public garden.
The Four Access Modifiers
Private
private is the most restrictive access modifier.
Private members can be accessed only within the same class.
Note: Classes and interfaces cannot be declared as
private.
Best Use Cases
- Passwords
- Internal variables
- Selenium locators
- Helper methods
Example
class Employee {
private String password = "admin123";
}
Default (Package-Private)
When no access modifier is specified, Java uses the default (package-private) access level.
Default members are accessible only within the same package.
Example
class Employee {
String name = "John";
}
Protected
protected members are accessible:
- Within the same package.
- By subclasses in other packages.
Example
class Animal {
protected void eat() {
System.out.println("Eating");
}
}
Public
public provides the widest level of access.
Public members can be accessed from any class in any package.
Example
public class Employee {
public void display() {
System.out.println("Employee");
}
}
Access Modifier Comparison
| Access Modifier | Same Class | Same Package | Subclass (Different Package) | Other Packages |
|---|---|---|---|---|
| private | ✅ | ❌ | ❌ | ❌ |
| default | ✅ | ✅ | ❌ | ❌ |
| protected | ✅ | ✅ | ✅ | ❌ |
| public | ✅ | ✅ | ✅ | ✅ |
Why It Matters in Real Projects
Framework developers use access modifiers to:
- Hide implementation details.
- Secure business logic.
- Prevent misuse of internal methods.
- Improve maintainability.
Real-Time Testing Example
In Selenium Page Object Model (POM):
- Web element locators are usually
private. - Test methods are
public. - Helper methods are often
protectedor package-private (default).
This improves encapsulation and prevents accidental access.
When Is the super Keyword Used?
The super keyword refers to the immediate parent class.
It is commonly used to:
- Access a parent class variable.
- Call a parent class method.
- Invoke a parent class constructor.
1. Accessing a Parent Class Variable
When parent and child classes have variables with the same name.
Example
class Animal {
String color = "White";
}
class Dog extends Animal {
String color = "Black";
void printColor() {
System.out.println(color);
System.out.println(super.color);
}
}
Output
Black
White
2. Calling a Parent Class Method
Used when a child class overrides a parent method.
Example
class Animal {
void eat() {
System.out.println("Eating...");
}
}
class Dog extends Animal {
void eat() {
System.out.println("Eating bread...");
}
void bark() {
System.out.println("Barking...");
}
void work() {
super.eat();
bark();
}
}
3. Calling a Parent Class Constructor
Use super() to invoke the parent constructor.
Example
class Animal {
Animal() {
System.out.println("Animal is created");
}
}
class Dog extends Animal {
Dog() {
super();
System.out.println("Dog is created");
}
}
Output
Animal is created
Dog is created
Real-Life Example
Imagine you and your father have the same name.
If someone calls that name, you clarify whether they mean you or your father.
Similarly, Java uses super to refer to the parent class.
Real-Time Testing Example
In Selenium Page Object frameworks, constructors commonly use:
super(driver);
This passes the WebDriver instance from the base page class to child page classes.
Purpose of break in a switch Statement
The break statement terminates the execution of a particular case.
Without break, Java continues executing the next cases.
This behavior is called fall-through.
Example
switch (value) {
case 1:
System.out.println("One");
break;
case 2:
System.out.println("Two");
case 3:
System.out.println("Three");
break;
}
If value is 2, the output will be:
Two
Three
Because there is no break after case 2.
Why Use break?
The break statement:
- Stops execution of the current case.
- Prevents accidental execution of subsequent cases.
- Improves code clarity.
Default Constructor After Defining an Explicit Constructor
Java automatically creates a default (no-argument) constructor only if no constructor is defined in the class.
Once you create any constructor, Java stops generating the default constructor.
Example
class Student {
Student(String name) {
}
}
This class has no default constructor.
Trying to create an object like this:
Student s = new Student();
Results in a compile-time error.
How to Add Both Constructors
If you need both constructors, define them manually.
class Student {
Student() {
}
Student(String name) {
}
}
Why Does Java Work This Way?
Java assumes that once you define a constructor, you want complete control over object creation.
Real-Life Example
Imagine bringing your own lunch to work.
Since you already have food, the office cafeteria won't automatically give you a free lunch.
If you want both, you must explicitly request it.
Real-Time Testing Example
In Selenium Page Object Model:
LoginPage(WebDriver driver)
is commonly used.
If a framework uses reflection to instantiate the class with a no-argument constructor, you must explicitly add one.
Quick Summary
- No constructor defined → Java creates a default constructor.
- Any constructor defined → Java does not generate a default constructor.
- If you need a no-argument constructor, define it explicitly.
Can You Override a Method by Changing Only the Return Type?
No.
Changing only the return type does not constitute method overriding.
The method signature consists of:
- Method name
- Parameter list
The return type is not part of the method signature.
Rules for Method Overriding
To override a method:
- Method name must be the same.
- Parameters must be identical.
- Return type must be the same or covariant (a subtype of the original return type).
Incorrect Example
class Parent {
int display() {
return 10;
}
}
class Child extends Parent {
String display() {
return "Hello";
}
}
This produces a compile-time error because only the return type has changed.
Correct Example
class Parent {
Number getValue() {
return 100;
}
}
class Child extends Parent {
Integer getValue() {
return 100;
}
}
Here, Integer is a subtype of Number, so this is valid covariant return type overriding.
Why Is This Important?
This rule ensures consistency in inheritance and prevents ambiguity when overriding methods in frameworks and APIs.
FAQs
1. What Is an Access Modifier in Java?
An access modifier is a keyword that controls the visibility of classes, methods, variables, and constructors.
Java provides four access modifiers:
privatedefaultprotectedpublic
2. What Is the Difference Between protected and default?
- default (package-private) allows access only within the same package.
- protected allows access within the same package and by subclasses in different packages.
3. When Is the super Keyword Used?
The super keyword is used to refer to the immediate parent class.
It can:
- Access parent variables.
- Call parent methods.
- Invoke parent constructors.
4. What Is the Purpose of break in a switch Statement?
The break statement terminates the current case and prevents execution from falling through to the next case.
5. Does Java Provide a Default Constructor If You Define Your Own?
No.
Once any constructor is explicitly defined, Java no longer generates the default no-argument constructor.
If you need one, you must define it manually.
6. Can You Override a Method by Changing Only the Return Type?
No.
Method overriding requires the same method name and parameter list.
The return type must be the same or a covariant subtype. Changing only the return type results in a compile-time error.