I have read in multiple places that final methods are early bound but none offers a satisfactory reason. I doubt how can it be so coz even in a final method called on parent class reference, compiler cannot say whether parent’s non final or child’s final method is called.
Please advice.
class Parent {
void meth() {
System.out.println("parent");
}
}
class Child extends Parent {
@Override
final void meth() {
// TODO Auto-generated method stub
System.out.println("child");
}
public static void main(String[] args) {
Parent parent = new Parent();
Parent child = new Child();
child.meth();
parent.meth();
}
}
In the above code method meth() called on child(a Parent reference) is a final method but then the JVM should need to use a method look up table at run time as in its the child or parent method being called.
Binding in java happens in two stages. At compile time the type of the reference as known to the compiler is used to bind the method to the highest method up the type hierarchy it can be. E.g. if calling toString() on a Number type variable, then the compiler knows it has to call Number.toString() or a sub-class override rather than Object.toString().
Secondly when invoking the method at runtime, the runtime type of the object is looked at and the most specific method in the type hierarchy is found and invoked. I.e. in the case of Number.toString above, if the object is an Integer it will find Integer.toString and call that.
If the method is final in the type of the reference / variable then this second step can be skipped because we know there can be no sub-class override. This is what Dima Rudnick means by the static type. So again with my example, if Number.toString was final, and the variable was type Number then we don’t need to look at the runtime type to know what method we’re invoking.
Note: for the purposes of this I’m assuming Object, Number and Integer all have a specific toString method rather than relying on the inherited one.