Search code examples
javajvmjavac

what happens between static and dynamic polymorphism


can't really find the proper answer. if we have:

1.Animal cat = new Cat();

2.Animal animal = new Animal();

Animal and Cat both has method makeSound();

1.as I understand early binding in Java happens during compile time and method call is bound depending on the reference type. so during compile time it makes decision to call method from Animal.

then we have runtime and it appears that the real object is Cat and there's an overriden method there and at this point late biding takes place?

my question will java first makes static binding and then during runtime checks again the actual object and rebind again?

They say compile binding is faster than runtime, but it looks like runtime binding will be involved anyway even if there's no overriden method in Cat? looks like overhead

  1. in the second case, no sense for Java to check the actual object? or it will check anyway?

also will annotation @Override somehow helps to make that decision?

I tried to Google and couldn't really find the straight answer and chat GPT messed me up completely


Solution

  • will java first makes static binding and then during runtime checks again the actual object and rebind again?

    Yes

    but it looks like runtime binding will be involved anyway even if there's no overriden method in Cat? looks like overhead

    That's kind of like asking why people also have breakfast in the morning when they will have dinner in the evening anyway.

    Static binding happens at compile-time and dynamic binding happens at runtime. They are completely different processes. For example, the compiler does overload resolution (e.g. choosing between foo(int) and foo(String)), so the JVM doesn't have to do it. If anything, doing everything at runtime would add runtime overhead.

    See this section of the JLS to see what happens at compile time and what happens at runtime respectively.

    Also, doing static binding has the additional benefit that you don't accidentally call a non-existent method, or that you have passed the wrong arguments. If the compiler succeeds in binding, that also means the method you are calling does exist and the argument types are valid too. You can be quite sure that the method call will succeed at runtime, and that you are not making any typos.

    in the second case, no sense for Java to check the actual object? or it will check anyway?

    It will check anyway. They both compile to an invokevirtual instruction, which does the method selection at runtime. You probably should not be using Java if the overhead for dynamic dispatch is a performance issue.

    Also note that if you call a static method, there is no dynamic dispatch. The JVM will try to find a method that matches the specified name, in one class.

    also will annotation @Override somehow helps to make that decision?

    No, @Override just makes the compiler check if you are actually overriding a method from the superclass, and if you aren't, tell you about it. See also my answer here.