Short answer
Overloading is same name, different parameter lists, resolved by the compiler at compile time based on the static types of the arguments.
Explanation
Overriding is a subclass providing a new implementation of an inherited method with the same signature, dispatched at runtime based on the object's actual type (dynamic dispatch via the vtable). A classic gotcha: choosing among overloads uses static types, so passing a List reference that actually holds an ArrayList still binds to the List overload.
Common mistakes
- Saying overloading is resolved at runtime — it is resolved at compile time from declared types.
- Thinking static methods can be overridden (they are hidden).