Java Tutorials: Overloading is compile-time binding
Have a look at the following example. There are three classes - Base, Derived and Test. As the name indicates class Derived extends class Base. The class Test has two overloaded methods with name methodA, with parameters Base and Derived respectively.
class Base{
}
class Derived extends Base{
}
class Test{
public void methodA(Base b){
System.out.println("Test.methodA(Base)");
}
public void methodA(Derived b){
System.out.println("Test.methodA(Derived)");
}
public static void main(String []args){
Test t = new Test();
Base b = new Base();
Base d = new Derived();
t.methodA(b);
t.methodA(d);
}
}
What is the output?
If your answer is
Test.methodA(Base)
Test.methodA(Derived)
This is wrong
For your surprise the answer is wrong. The actual output is
Test.methodA(Base)
Test.methodA(Base)
Surprised?
This is because overloading is compile-time binding. When the compiler sees the line t.methodA(d);
It checks the data type of 'd', which is declared as 'Base'. So it looks for the method, methodA(Base) and binds the call to this method and hence the result.
Let us look at another common problem. When the programmers think to override the 'equals', but endup really overloading the method, there by creating some unforeseen problems.
Have a look at the following code, and say whether the equals method and the hashCode are implemented in the correct way?
public class EqualsOverloadTest {
String id;
public EqualsOverloadTest(String id){
this.id = id;
}
public boolean equals(EqualsOverloadTest other){
return (other!=null) && this.id.equals(other.id);
}
public int hashCode() {
return id.hashCode();
}
}
In the first go, anyone will say the equals method is implemented correctly.
It follows all the constraints for the 'equals' method, and also implements the 'hashCode()' method following the same contract. But, if you look closer, you fill notice that, the 'equals' method really overloads the Object.equals(Object) method, instead of over loading it.
To prove that this won't work, let me give a simple program. In the main method, we are creating two EqualsOverloadTest objects with the same id. The two objects are added into the Set. Then we are printing the size of the set.
public static void main(String[] args) {
EqualsOverloadTest first = new EqualsOverloadTest("123");
EqualsOverloadTest second =
new EqualsOverloadTest(new String("123"));
System.out.println(first.equals(second));
Set set = new HashSet();
set.add(first);
set.add(second);
System.out.println(set.size());
}
We will expect the size of the Set to be '1' since the two Objects are equal. But it will print as '2'.
This is because we didn't override the 'equals' method. Whereas the first check with the equals method returned true, because we called the method as equals(EqualsOverloadTest), hence the proper method was called. But withing the set, it called the method equals(Object), which is not implemented, so uses the Object.equals(Object), which really checks whether they both are same instance or not. Hence we get an unexpected behaviour.
Summary:
Overloading is a static or compile-time binding and Overriding is dynamic or run-time binding.