In Java, method overloading and overriding are resolved according to specific rules. During overloading, the compiler selects the most appropriate method from all versions at compile time based on the argument types at the call site.
Important points:
Example:
class Super { void print(Number n) { System.out.println("Super Number"); } } class Sub extends Super { void print(Integer i) { System.out.println("Sub Integer"); } } ... Sub s = new Sub(); s.print(5); // Sub Integer s.print(5.0); // Super Number
Here, print(Integer) will be called for an argument of type Integer, while the parent method will be called for type Double.
If a method is overridden and overloaded in the subclass, which one will be called during polymorphism?
Answer: In polymorphism, the version of the method is always chosen based on the actual type of the object for overridden methods. For overloaded methods, the selection is made at compile time based on the reference type.
class A { void test(Number n) { System.out.println("A:Number"); } } class B extends A { void test(Integer n) { System.out.println("B:Integer"); } @Override void test(Number n) { System.out.println("B:Number"); } } ... A obj = new B(); obj.test(1); // Calls B:Number, despite the existence of test(Integer)
Story
A developer added an overloaded version of a method in the subclass, expecting it to be called for all inherited classes. In production, it became clear that calls through the parent class reference led to method selection based on reference type rather than object type. As a result, the necessary logic was not executed.
Story
In a large project, they mistakenly overloaded the equals(Object) method with the signature equals(MyClass obj), thinking it would replace the standard equals. When compared in HashSet collections, the default equals(Object) was used, leading to logic mismatches and data loss.
Story
When adding a new varargs version of a method to the class hierarchy, it seemed that the necessary version would be called for arrays. However, when passing an array explicitly, the compiler selected the wrong overload, resulting in incorrect processing and the bug remained unnoticed for a long time.