Yesterday I had a two-hour technical phone interview (which I passed, woohoo!), but I completely muffed up the following question regarding dynamic binding in Java. And it's doubly puzzling because I used to teach this concept to undergraduates when I was a TA a few years ago, so the prospect that I gave them misinformation is a little disturbing...
Here's the problem I was given:
/* What is the output of the following program? */ public class Test { public boolean equals( Test other ) { System.out.println( "Inside of Test.equals" ); return false; } public static void main( String [] args ) { Object t1 = new Test(); Object t2 = new Test(); Test t3 = new Test(); Object o1 = new Object(); int count = 0; System.out.println( count++ );// prints 0 t1.equals( t2 ) ; System.out.println( count++ );// prints 1 t1.equals( t3 ); System.out.println( count++ );// prints 2 t3.equals( o1 ); System.out.println( count++ );// prints 3 t3.equals(t3); System.out.println( count++ );// prints 4 t3.equals(t2); } }
I asserted that the output should have been two separate print statements from within the overridden equals()
method: at t1.equals(t3)
and t3.equals(t3)
. The latter case is obvious enough, and with the former case, even though t1
has a reference of type Object, it is instantiated as type Test, so dynamic binding should call the overridden form of the method.
Apparently not. My interviewer encouraged me to run the program myself, and lo and behold, there was only a single output from the overridden method: at the line t3.equals(t3)
.
My question then is, why? As I mentioned already, even though t1
is a reference of type Object (so static binding would invoke Object's equals()
method), dynamic binding should take care of invoking the most specific version of the method based on the instantiated type of the reference. What am I missing?
In dynamic binding, the method call is bonded to the method body at runtime. This is also known as late binding. This is done using instance methods.
In Java static binding refers to the execution of a program where type of object is determined/known at compile time i.e when compiler executes the code it know the type of object or class to which object belongs. While in case of dynamic binding the type of object is determined at runtime.
Dynamic binding is not a type of polymorphism; rather dynamic binding is how polymorphism is "implemented" or how it works. And dynamic binding and runtime binding are the same thing. "Dynamic Binding" is the more academic or computer science based name for it. And "run time binding" is a more every day term for it.
Explanation: Dynamic binding is applied to instance methods, not static methods. Static methods are bound in the compile time.
Java uses static binding for overloaded methods, and dynamic binding for overridden ones. In your example, the equals method is overloaded (has a different param type than Object.equals()), so the method called is bound to the reference type at compile time.
Some discussion here
The fact that it is the equals method is not really relevant, other than it is a common mistake to overload instead of override it, which you are already aware of based on your answer to the problem in the interview.
Edit: A good description here as well. This example is showing a similar problem related to the parameter type instead, but caused by the same issue.
I believe if the binding were actually dynamic, then any case where the caller and the parameter were an instance of Test would result in the overridden method being called. So t3.equals(o1) would be the only case that would not print.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With