Method Overloading vs Overriding in Java: Key Differences and Common Pitfalls
This article explains Java's two polymorphism mechanisms—static overload and dynamic override—detailing definitions, compiler rules, valid code examples, a side‑by‑side comparison table, and frequent pitfalls such as static method hiding, access‑modifier changes, and exception widening.
Java’s Two Polymorphism Mechanisms
Static (compile‑time) polymorphism is achieved through method overloading, while dynamic (run‑time) polymorphism is realized by method overriding.
Method Overload (Overload)
Official definition
In the same class, multiple methods can share the same name but must have different parameter lists.
Conditions that trigger overload
Different number of parameters
Different parameter types
Different order of parameter types
Valid overload examples
public class OverloadDemo {
// basic method
public void test(int a) { System.out.println("参数为int类型"); }
// overload 1: different number of parameters
public void test(int a, int b) {}
// overload 2: different parameter type
public void test(String a) {}
// overload 3: different order (different types)
public void test(int a, String b) {}
public void test(String b, int a) {}
}Four items that do NOT affect overload resolution
Return type, access modifier, declared exceptions, and method modifiers are ignored; changing any of them alone does not create a new overload and will cause a compile‑time error.
// error: only return type differs
public void demo() {}
public int demo() { return 1; }
// error: only access modifier differs
public void func() {}
private void func() {}Compilation‑time mechanism
The compiler builds a unique method signature from the method name and parameter list; the binding is fixed at compile time, so the called method cannot change at runtime.
Method Override (Override)
Official definition
In a subclass, an instance method that is non‑private, non‑static, and non‑final can be reimplemented with the same signature as the superclass method.
Five mandatory rules
Method name and parameter list must be identical to the superclass method.
Access level in the subclass must be at least as permissive as in the superclass.
Return type may be covariant (subclass type for reference types).
Checked exceptions thrown by the subclass method must be the same or narrower.
Methods that are private, static, final, or constructors cannot be overridden.
Valid override examples
class Person {}
class Student extends Person {}
class Father {
public Person getInfo() { return new Person(); }
public void say() throws Exception {}
}
class Son extends Father {
// covariant return
@Override
public Student getInfo() { return new Student(); }
// narrower exception
@Override
public void say() throws RuntimeException {}
}Dynamic binding
At runtime the JVM uses the virtual method table (vtable) to locate the overridden method based on the actual object type.
Common Pitfalls
1. Static methods “look like” overrides but are actually hidden
class Father { public static void show() { System.out.println("父类静态方法"); } }
class Son extends Father { public static void show() { System.out.println("子类静态方法"); } }
class Test { public static void main(String[] args) {
Father f = new Son();
f.show(); // prints "父类静态方法"
} }Static methods belong to the class, are bound at compile time, and do not participate in polymorphism.
2. Different parameter type = overload, not override
class Father { public void test(Object obj) {} }
class Son extends Father {
// not an override – overload
public void test(String str) {}
}Use @Override to let the compiler verify correct overriding.
3. Private methods cannot be overridden
class Father { private void test() { System.out.println("父类私有方法"); } }
class Son extends Father { public void test() { System.out.println("子类方法"); } }The subclass method is a new method, unrelated to the superclass private method.
4. Reducing access level causes a compile‑time error
Subclass access cannot be more restrictive than the superclass (public > protected > package‑private > private).
5. Widening checked exceptions breaks overriding
The subclass method may throw the same or a narrower checked exception, never a broader one.
6. Varargs and array parameters conflict
// compile error: both signatures are considered the same
public void fun(int[] arr) {}
public void fun(int... arr) {}7. Changing only the parameter name does not create an overload
Overload resolution ignores parameter names.
@Override Annotation
Forces the compiler to check that the method truly overrides a superclass method.
Prevents mistakes such as wrong parameter types, return types, static hiding, or incorrect access modifiers.
Improves code readability by clearly marking overridden methods.
Development guideline: always add @Override to overridden methods.
Conclusion
Overloading provides compile‑time static polymorphism within a single class, enabling flexible method signatures. Overriding enables run‑time dynamic polymorphism across inheritance hierarchies, allowing subclasses to customize behavior. Remember: overload = different parameters; override = inheritance; overload is bound at compile time; override is resolved at runtime.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Tech Workshop
Focused on Java backend technologies, sharing fundamentals, multithreading, JVM, the Spring ecosystem, microservices, distributed systems, high concurrency, source‑code analysis, and practical experience. Continuously delivers high‑quality original content, interview guides, and learning roadmaps to help Java developers progress from beginner to advanced, enhancing technical skills and core competitiveness.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
