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) |