I am practicing for a test and I came across this exercise about overloading and static and dynamic binding. The output of the following code is asked:
class
Static binding happens at compilation time and dynamic binding at runtime.
Static binding is responsible for selecting signature (name and argument types) of method which should be executed. It uses
Compiler selects signature from variable type on which method is invoked, so Object o = "abc"; will not allow you to invoke o.substring(1,2); because compiler will not be able to find substring(int, int) signature in Object class (which is type of o variable on which substring method was invoked).
Dynamic binding is responsible for finding and invoking code of method selected by static binding at compilation time. It will try to find code of method in type of actual instance held by variable. In other words if you have Animal a = new Cat(); a.makeSound(); you can expect to get as result "Mew" because at runtime JVM will search and invoke code of makeSound starting from Cat class. If implementation will not be provided in that class JVM will search for it in ancestor(s) until it finds one from which it was inherited.
I renamed classes and variables in your example a little to hopefully make it more readable:
class A {
public void print(A a) {
System.out.println("A.print(A)");
}
}
class B extends A {
public void print(A a) {
System.out.println("B.print(A)");
}
public void print(B b) {
System.out.println("B.print(B)");
}
}
class C extends B {
public void print(A a) {
System.out.println("C.print(A)");
}
public void print(B b) {
System.out.println("C.print(B)");
}
public void print(C c) {
System.out.println("C.print(C)");
}
}
class OverloadingDemo {
public static void main (String [] args) {
A ab = new B();
A ac = new C();
B bb = new B();
B bc = new C();
bc.print(new A());
bc.print(new C());
bc.print(new B());
ab.print(new C());
ac.print(new C());
ac.print(new B());
bb.print(new C());
}
}
(variable naming -> variable of type X holding instance of type Y is named xy).
So, when we execute
bc.print(new A());
print method signature available in class B which can handle instance of type A. In this case it will be print(A). C (since this is type of instance held by bc variable) which means we will see C.print(A).Similarly in case of bc.print(new C());
print method for C argument available in B class, which for C is print(B) (since there is no print(C) there and B is closest supertype). C class (since this is instance which bc holds).So it will invoke C.print(B).