Definition
The answer is no, for one fundamental reason:
- static methods belong to the class, not to objects. Overriding is a runtime polymorphism concept – the JVM decides which method to call based on the actual object type. Static methods are resolved at compile time based on the reference type. There is no polymorphic dispatch.
- A subclass can have its own main. But this is method hiding, not overriding. The parent's main still exists and is callable via
ParentClass.main(args).
Overriding is like a bank branch customizing a service inherited from head office – when a customer walks in, they get the branch's version. But main is like a notice pinned to a specific office wall (the class). Each office can have its own notice, but walking into one office does not magically change the notice in another. They are independent.
Understanding the Concepts
Why can static methods not be overridden?
Overriding means: the JVM looks at the actual object type at runtime and calls the corresponding method. This is dynamic dispatch, the mechanism behind polymorphism. Static methods do not participate in dynamic dispatch – they are dispatched on the class at compile time based on the reference type.
package com.bank;
public class BankApp {
public static void main(String[] args) {
System.out.println("BankApp main");
}
}
public class MobileBankApp extends BankApp {
// This is method HIDING, not overriding
public static void main(String[] args) {
System.out.println("MobileBankApp main");
}
}
java BankApp # Output: BankApp main
java MobileBankApp # Output: MobileBankApp main
Each class has its own independent main. The JVM calls whichever class you specify on the command line. There is no polymorphic dispatch.
What is the difference between hiding and overriding?
The key difference is when the decision is made. Overriding is a runtime decision based on the object type. Hiding is a compile-time decision based on the reference type.
public class Parent {
public static void greet() { System.out.println("Parent"); }
public void hello() { System.out.println("Parent hello"); }
}
public class Child extends Parent {
public static void greet() { System.out.println("Child"); } // HIDES
@Override
public void hello() { System.out.println("Child hello"); } // OVERRIDES
}
Parent p = new Child();
p.greet(); // "Parent" – static: resolved by REFERENCE type (Parent)
p.hello(); // "Child hello" – instance: resolved by OBJECT type (Child)
| Feature | Overriding (instance) | Hiding (static) |
|---|---|---|
| Resolved by | Object type (runtime) | Reference type (compile time) |
| @Override works? | Yes | No (compiler error) |
| Polymorphic? | Yes | No |
| Binding | Late binding | Early binding |
Can you put @Override on main?
No. The compiler rejects @Override on any static method, including main.
public class ChildApp extends ParentApp {
// @Override // COMPILE ERROR: method does not override a superclass method
public static void main(String[] args) {
System.out.println("ChildApp");
}
}
What does the bytecode look like?
At the bytecode level, static method calls use the invokestatic instruction, which specifies the exact class and method at compile time. Instance method calls use invokevirtual, which looks up the method in the object's virtual method table at runtime.
// Compile-time bytecode for static call:
// invokestatic BankApp.main:([Ljava/lang/String;)V
// Compile-time bytecode for instance call:
// invokevirtual Parent.hello:()V ← resolved at runtime to Child.hello()
This is why static methods cannot be overridden – the JVM does not look at the object's type when executing invokestatic.
What are common mistakes?
- Assuming child's main is called polymorphically.
java ParentAppalways runs ParentApp.main, even if ChildApp exists with its own main. - Thinking @Override works on static methods. It does not – the compiler rejects it.
- Confusing hiding with overriding. Both define a method with the same name, but hiding is compile-time, overriding is runtime.
What should a senior engineer know?
- In Spring Boot, you typically have one main class. The
@SpringBootApplicationclass has main. Subclassing it and adding another main would be confusing and pointless. - The JVM entry point is always
ClassName.main(args). It is a static call, not an instance dispatch. This is by design – the JVM does not create any objects before main runs, so there is no object to dispatch on. - In a banking project at National Bank of India, Rajesh keeps a single main class per deployable artifact. Utility classes that need their own main (like migration tools) are placed in separate modules with their own main class.
Visual Overview
Static method (like main): Instance method:
resolved by REFERENCE type resolved by OBJECT type
at COMPILE time at RUNTIME
→ hiding, not overriding → overriding (polymorphism)
Parent p = new Child();
p.main(args) → Parent.main() p.hello() → Child.hello()
(static: Parent reference wins) (instance: Child object wins)
Key Takeaway
No, the main method cannot be overridden because it is static, and static methods are resolved by the reference type at compile time, not by the object type at runtime. This means there is no polymorphic dispatch for static methods.
A subclass can define its own main(String[] args), but this is method hiding, not overriding. The parent's main and the child's main are independent. The JVM calls whichever class you specify on the command line.
One sentence to remember: static methods cannot be overridden – a subclass's main hides the parent's rather than overriding it, and there is no polymorphic dispatch.
---