javapolymorphismoverridingoverloadingstatic-polymorphism

Is it true to say that every run time binding was a static binding during compilation?


I'm pretty confused about the topic binding. As we know in static binding, the type of reference is checked to determine the binding, not the object it is referencing, and in dynamic binding, the type of object the reference is pointing is taken into consideration.

class A
{
    void show()
    {
        System.out.println("From A");
    }
}
class B extends A
{
    void show()
    {
        System.out.println("From B");
    }
}
class Main
{
    public static void main(String[] quora)
    {
        A a1 = new A();
        A a2 = new B();

        a1.show(); //line 1
        a2.show(); //line 2
    }
}

In the above example, we can see during compile time, both Line1 and line2 will be treated by static binding and they will link to the A-class method show( since the type of reference is A). But during runtime, the call is resolved and line1 links to the A-class method show() and line2 links to the B-class method i.e, type of object or we can say dynamic binding.

So my main intention is to know the following.

  1. Is dynamic binding always results after static binding? or I'm understanding something wrong?

  2. If it's true then is it true to say every method is dynamically linked during the run time?

  3. Can we generalise it?


Solution

  • Basically, every time you call a method, the compiler has to figure out which overload to call, based on the types and the arguments you pass to the method. This is static binding. Then at runtime, the runtime will figure out which implementation of the overload (which is already decided at this point) to call.

    Consider:

    class A
    {
        void f(Object o)
        {
            System.out.println("From A");
        }
    }
    class B extends A
    {
    
        void f(Object o)
        {
            System.out.println("From B (Object)");
        }
    
        void f(String s)
        {
            System.out.println("From B (String)");
        }
    }
    

    And you do:

    A a = new B();
    a.f("");
    

    What happens? At compile time, the compiler has chosen the overload f(Object) due to the type of a being A (there is only one method to choose from!). Then at runtime, since a actually refers to an instance of B, B's implementation of the f(Object) overload gets called, printing From B (Object). One misconception I've seen is to expect the output to be From B (String). This is wrong because the compiler doesn't know about the existence of this overload on a.

    Is dynamic binding always results after static binding?

    As we can see from the results of the above code, the answer is yes. Static binding happens at compile time, dynamic binding happens at runtime, so the former always happens first.

    If it's true then is it true to say every method is dynamically linked during the run time?

    I'm not sure what you mean by this, so hopefully the detailed explanation above would have answered this already.

    no matter what, there's always gonna be static binding and then dynamic binding for every method call?

    Yes, but sometimes these two processes can go very quickly though, because there is very few choices. You probably don't need to make a "choice" in dynamic binding when the class you are calling the method on is a final class, do you?