When overriding a method in Java, the access level cannot be narrowed, but the return type can be narrowed (covariant return type). Let’s break it down.
1. Access Level in Method Overriding
❌ Cannot Narrow the Access Level
- The overridden method in the child class must have the same or a broader (more permissive) access modifier than the parent class.
- It cannot be more restrictive than the original method.
Access Level Hierarchy (from most restrictive to least restrictive):
private → default (package-private) → protected → public
Example of an Invalid (Narrowing) Override:
class Parent {
protected void show() {
System.out.println("Parent method");
}
}
class Child extends Parent {
private void show() { // ❌ Compilation error: We cannot reduce access from protected to private
System.out.println("Child method");
}
}
⛔ Error: “Cannot reduce the visibility of the inherited method from Parent“
Valid (Same or Broader) Override Examples:
class Parent {
protected void show() {
System.out.println("Parent method");
}
}
class Child extends Parent {
public void show() { // ✅ Valid: 'public' is broader than 'protected'
System.out.println("Child method");
}
}
Rules for Overriding Access Levels:
| Parent Class Access Modifier | Allowed in Child Class |
|---|---|
| private | ❌ Cannot be overridden (not inherited) |
| default (package-private) | ✅ default, protected, public (same or broader) |
| protected | ✅ protected, public (same or broader) |
| public | ✅ public only (cannot be reduced) |
2. Return Type in Method Overriding
✅ Can Be Narrowed (Covariant Return Type)
- Java allows narrowing the return type in an overridden method.
- The overridden method must return the same type or a subclass of the original return type.
Example of Covariant Return Type:
class Parent {
Parent getObject() {
return new Parent();
}
}
class Child extends Parent {
@Override
Child getObject() { // ✅ Valid: Child is a subclass of Parent
return new Child();
}
}
🚀 This is called a covariant return type, introduced in Java 5.
Example of an Invalid (Widening) Return Type:
class Parent {
Number getValue() {
return 10;
}
}
class Child extends Parent {
@Override
Object getValue() { // ❌ Compilation error: Object is not a subclass of Number
return "String";
}
}
⛔ Error: “getValue() in Child cannot override getValue() in Parent; return type Object is not compatible with Number“
Valid Covariant Return Type Examples:
| Parent Return Type | Allowed in Child |
|---|---|
Number | Integer, Double, Float, Long |
Animal | Dog, Cat, Lion (subclasses of Animal) |
Collection<E> | List<E>, Set<E>, ArrayList<E> |
Final Answer
| Feature | Can Be Narrowed? | Example |
|---|---|---|
| Access Level | ❌ No | protected → private (invalid) |
| Return Type | ✅ Yes (if covariant) | Parent → Child (valid) |