1

Runtime binding happens at runtime because compiler cannot decide which function to execute at compile time but why compiler cannot decide at compile time ?

class Animal{
    void eat(){ System.out.println("animal is eating..."); }
}
class Dog extends Animal{
    @Override 
    void eat(){ System.out.println("dog is eating..."); }
}
class Cat extends Animal{
    @Override 
    void eat(){ System.out.println("cat is eating..."); }
}

class Example {
    public static void main(String args[]){
        Animal a = new Dog();
        a.eat();
        Animal b = new Cat();
        b.eat();
    }
}

Output:

dog is eating...
cat is eating...

These question does not answer my Question

Pshemo
  • 122,468
  • 25
  • 185
  • 269
Saurabh Dhage
  • 1,478
  • 5
  • 17
  • 31
  • Fundamentally it's not clear what you would like to happen, or why you think it would be better than how Java is actually designed. – Jon Skeet Oct 03 '21 at 07:59
  • 1
    "...because compiler cannot decide which function to execute at compile time" to be more precise compiler knows *signature* of method which needs to be executed, but it doesn't know yet from where it should take *code* (body) of that method, because that decision depends on type of *value* held by variable at *runtime* so that body needs to be bound dynamically. It is easier to understand this logic for code like `void someMethod(SomeInterface val){ val.methodFromInterface(); }` where we compiler can't know what type of object will be passed to `someMethod` as argument. – Pshemo Oct 03 '21 at 08:02
  • 10
    Imagine for a second that instead of `Animal a = new Dog()` the initialization was `Animal a = SomeClassFromALibrary.getAnAnimalBasedOnSomeConfiguration()`. Now the compiler has no way of knowing what type `a` will actually end up referencing. It could be `Dog` or `Cat` or even `Cow` (which may have been declared in some other library). In short: the compiler doesn't necessarily have a complete view of the program that will end up executing. It only sees a small subset and must act accordingly. – Joachim Sauer Oct 03 '21 at 08:06
  • but what if `Dog d=new Dog()` then here also compiler does not know type of object.so how does it is not runtime binding? – Saurabh Dhage Oct 03 '21 at 08:14
  • 1
    What do you mean by "how does it is not runtime binding"? Again, what behavior do you think would be better? This question is really unclear IMO. – Jon Skeet Oct 03 '21 at 08:17
  • 2
    @SaurabhDhage: that's just the rules. Since it can't be done in all cases, it never does it. Doing it *sometimes* would unnecessarily complicate both the compiler and the runtime (since they would now both need to be able to handle two cases). Note that `private` and `static` methods actually get fully "locked in" during compilation, so no dynamic lookup is necessary in these cases (since the rules of the language guarantee that there's only one possible candidate for those). – Joachim Sauer Oct 03 '21 at 08:18
  • 1
    Just want to add that aside from `private` and `static` also **`final`** methods are not polymorphic (there is no dynamic binding for them since compiler knows that those can't be overridden so they can't have *alternative bodies* in subclasses). – Pshemo Oct 03 '21 at 08:27

1 Answers1

4

Runtime binding happens at runtime because compiler cannot decide which function to execute at compile time ...

This is incorrect, at least in the case of Java.

Runtime binding in Java is not a result of short-comings of the Java compiler. It is by design.

Runtime binding in Java has many advantages:

  • It means that you don't have to compile and link all of your code at the same time whenever you make a change to the code base. This makes development faster.

  • It means that you don't have to compile and link against a specific version of the Java runtime. In short, it enables "write once, run everywhere"1.

  • It means that your application can make used of plugins provided by 3rd parties.

  • Indeed, the application can can load different versions of things to deal with platform differences and so on.

And the nice thing is that Java does this while maintaining runtime type-safety.


... but why compiler cannot decide at compile time ?

Well, they could have designed Java so that the compiler (or linker) could have bound everything at compile time. But Java would be a very different language if they did.

But given that they designed Java the way that they did, it is actually not possible to determine certain things at compile time that seem obvious to a reader2. Often this apparent shortcoming is because the reader is not taking into account of things like:

  • new classes being added to the type hierarchy, or
  • existing classes being modified to have different behavior, and recompiled individually.

Joachim's comment gives a nice example:

"Imagine for a second that instead of Animal a = new Dog() the initialization was Animal a = SomeClassFromALibrary.getAnAnimalBasedOnSomeConfiguration(). Now the compiler has no way of knowing what type a will actually end up referencing. It could be Dog or Cat or even Cow (which may have been declared in some other library). In short: the compiler doesn't necessarily have a complete view of the program that will end up executing. It only sees a small subset and must act accordingly."


1 - That is ... to the extent that "write once, run everywhere" is reality rather than marketing hype.
2 - As far as I can tell, your example does not illustrate this.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • The compiler doesn't check in the imported libraries for the function definition? – Mehdi Charife Feb 13 '23 at 20:15
  • Yes it does. But the runtime system **also** checks ... in case the definition has changed since the compiler checked it. That's the point of *runtime* binding. – Stephen C Feb 14 '23 at 02:06