How does Java know the exact call address on runtime if the given type is interface? For example,
// A few definitions
public interface In {
void method();
}
public class A implements In {
public void method() {
System.out.println("A");
}
}
public class B extends A {
public void method() {
System.out.println("B");
}
}
There are some interface, class definitions, and use those as follow.
// ... Java stuff...
public int main() {
test1(new A()); // stdout A
test2(new B()); // stdout A
}
public void test1(In i) {
i.method();
}
public void test2(A a) {
a.method();
}
From the result of test1, Java runtime seems to know exact given i
's type cause test1
print out A
which is given by main
as an argument.
The result of test2, if given parameter type is not an interface, Java runtime doesn't know the given type B
and just access to method of A
which is actually not given by main
.
Second case test2
is quite straightforward to me because compiler doesn't know which subtype of A
is given as a parameter, so just compile to bytecode just call method of A
. So the runtime just call A
's method.
But first case test1
, how can the runtime know exactly what a given type is?
Java basically has 2 ways to determine what method implementation to run:
Static dispatch is when you compile the code, Java will look at the type of the variable you are using and select the method for that type.
In Dynamic dispatch, however, the decision of what method to execute is done by the receiving object irrespective of any types of variables. This is done at runtime.
So you can think of it as Java "asking" the object to execute the selected method, and then the Java object looking to see if it has that method , and if it doesn't have the method implemented in its class it "asks" it's super class. And that process goes all the way to the root class of the hierarchy.
Note: in Java objects always know what their class is. You can call methods like object.getClass()
. So internally you can imagine it takes advantage of this fact.
Actual implementation details are probably slightly more nuanced, and full of optimizations, but this is the mental model you can use.
In fact, in Smalltalk (the first or second OO language, depending on who you ask) this is exactly how it would happen. A "method call" would send a "message" to the object, and the object would either execute the method or pass it to the superclass. If no implementation was found you'd get an exception (since Smalltalk had no static typing).
This is why dynamic dispatch is sometimes referred to as "message passing".