Definition
Two types that cannot be overridden:
- private: Not visible outside the class. A subclass that defines the same-named method is creating a new, independent method. It has no relationship to the parent's private method.
- static: Belongs to the class, not to objects. A subclass can define the same static signature, but this is hiding (compile-time resolution by reference type), not overriding (runtime resolution by object type).
A bank's private internal audit procedure (private method) is invisible to branch offices. A branch can create its own audit procedure with the same name, but it has no connection to the head office's procedure. A bank notice posted on a specific wall (static method) can be covered by a branch's own notice (hiding), but the head office's notice is still there underneath – looking from the head office reference, you see the original.
Understanding the Concepts
Why can private methods not be overridden?
Overriding requires the subclass to see the parent's method. Private methods are not visible outside the class.
public class Account {
private void audit() {
System.out.println("Account audit");
}
public void process() {
audit(); // calls Account.audit()
}
}
public class SavingsAccount extends Account {
// This is a NEW method, NOT an override. Account.audit() is invisible.
private void audit() {
System.out.println("SavingsAccount audit");
}
}
Account a = new SavingsAccount();
a.process(); // prints "Account audit" (not SavingsAccount's)
// Because process() calls this.audit() which is Account's private audit()
The subclass's audit() is completely independent. The parent's process() still calls the parent's private audit().
Why can static methods not be overridden?
Static methods are resolved at compile time by the reference type, not at runtime by the object type.
public class Bank {
public static String getType() { return "GENERIC"; }
}
public class SavingsBank extends Bank {
public static String getType() { return "SAVINGS"; } // HIDES, not overrides
}
Bank b = new SavingsBank();
System.out.println(b.getType()); // "GENERIC" (reference type: Bank)
System.out.println(SavingsBank.getType()); // "SAVINGS" (explicit class)
Can you use @Override?
public class SavingsAccount extends Account {
// @Override on a method that matches a parent's PRIVATE method:
// compiles, but it is not actually overriding – it is a new method
// (the compiler does not see the parent's private method)
// @Override on a STATIC method:
// @Override
// public static String getType() { } // COMPILE ERROR: cannot override static
}
Summary table
| Method type | Can be overridden? | What happens if subclass defines same? | @Override allowed? |
|---|---|---|---|
| public/protected instance | Yes | Overriding (runtime dispatch) | Yes |
| private instance | No | New independent method | Yes (but misleading) |
| static (any access) | No | Hiding (compile-time dispatch) | No (compiler error) |
| final instance | No | Compile error | No |
What are common mistakes?
- Thinking a subclass's same-named private method overrides the parent's. It does not. They are independent.
- Thinking static methods are polymorphic.
parentRef.staticMethod()calls the parent's version. - Using @Override on static. Compiler rejects it.
What should a senior engineer know?
- Private methods in interfaces (Java 9+) are for code reuse within default methods. They cannot be overridden because they are private.
- Virtual dispatch is the mechanism for overriding. Private and static methods bypass the virtual method table because they are resolved statically.
- In Spring proxies, calling a private method on
thisinside a @Transactional class bypasses the proxy. The transaction is not applied. This is a common source of bugs.
Visual Overview
Overridable: public/protected instance methods → runtime dispatch
NOT overridable: private → invisible to subclass (new method, not override)
static → hidden, not overridden (compile-time dispatch)
final → compiler rejects any attempt
Account a = new SavingsAccount();
a.process() → calls Account.audit() (private, not overridden)
a.getType() → calls Bank.getType() (static, not overridden)
a.calculateRate() → calls SavingsAccount.calculateRate() (overridden!)
Key Takeaway
Private methods cannot be overridden because they are invisible to subclasses. A subclass can define a method with the same name, but it is a completely new, independent method with no relationship to the parent's private method.
Static methods cannot be overridden because they belong to the class, not to objects. A subclass can define the same static signature, but this is method hiding: the call is resolved by the reference type at compile time, not by the object type at runtime.
Only public and protected instance methods participate in overriding and runtime polymorphism.
One sentence to remember: private is invisible so it cannot be overridden, static is resolved at compile time so it can only be hidden – neither participates in polymorphism.
---