6

I've read through some articles about static binding and dynamic binding in Java. And I have the following question (I've searched a lot but not found any mention about it yet):

For example, I have the following lines of code:

Person a = new Student(); // Student is a subclass of Person
a.speak();

What we've already known is that at compile-time, the compiler will checks whether there exist method definition for speak() in class Person and call it if it exists. And at run-time, it will call the speak() method of the actual object to which a is pointing (The actual object in this case is clearly Student)

So my question is why it doesn't directly call the speak() method of class Student at compile-time, but wait until run-time to do that? Are there any reasons behind this?

DunDev
  • 210
  • 2
  • 13
  • Because compiling your software is different than running it. – Zaki Anwar Hamdani Nov 23 '17 at 04:37
  • Because *you* told the compiler that `a` should be treated as `Person` rather than `Student`. And why should it compile the code in a different way than you requested? What advantage are you assuming for that different strategy? – Holger Jan 03 '18 at 14:52

3 Answers3

5

When the code compiles, sometimes,it is not clear which method needs to be invoked.It can be determined only at runtime.

Take this simple code as an example.

class Animal{   

    public void makeNoise(){
       System.out.println("Default");
    };
}

class Dog extends Animal{

    //override the makeNoise()
    public void makeNoise(){
        System.out.println("Woof");
    };
}

class Cat extends Animal{

        //override the makeNoise()
        public void makeNoise(){
            System.out.println("Meow");
        };
    } 

public class Sounds{

    public static void AnimalSounds(Animal animal){
    animal.makeNoise();
    }

    public static void main(String args[]){

        Animal dog = new Dog();     
        Animal cat = new Cat(); 
        AnimalSounds(dog);
        AnimalSounds(cat);  
    }
}

AnimalSounds(Animal animal) method takes any object that passes ISA test of Animal and invoke the respective method of that object. As you can see, it removes code duplication as well since we can use the same method on different types of objects.

Hope this address your concern.

Supun Amarasinghe
  • 1,443
  • 3
  • 12
  • 24
  • Thanks first. But can you provide some details on "sometimes,it is not clear which method needs to be invoked" on your example above? – DunDev Nov 23 '17 at 04:58
  • animal.makeNoise(); here, at compile time it is not known the type of the object. At run time , you pass a particular animal object and based on that, it invokes the respective method of that animal (ex: Dog or Cat) – Supun Amarasinghe Nov 23 '17 at 05:03
2

To understand this topic you should know what are compilation and run-time processes in general. In short, when you build your app compiler goes through all your code and checks for consistency, safety and run-ability. If there is no error founded by compiler it generates class files from your source code (java files). When the app is running it means that your class files are loaded into memory and JVM executing your app instruction by instruction.

From your example:

Person a = new Student(); // Student is a subclass of Person
a.speak();     

Compilation process: Compiler checks this line: Person a = new Student(); for type safety (compatibility). So, if student is a person compilation goes to next line else it fails. In next line: a.speak(); compiler looks at a type, found that it's a Person and looks for speak() method at Person type. If that method is not founded by compiler compilation process fails.

Runtime process: When JVM executes this line: Person a = new Student(); it goes through initialization process from top (parent class) to bottom (child class). In next line: a.speak(); JVM founds student object through reference a looks for method speak() if it's founded in Student then executes it, otherwise it runs speak() method from parent class Person.

Another examples from inheritance subject:

class Person {
    public void speak() {}
    public void think() {}
}

class Student extends Person {
    @Override
    public void speak() {}
    public void speakALot() {}
}

Person a = new Student();
a.speak(); // calling overrided version of speak() 
a.think(); // since this method is not overrided in child class it will be called from parent class
a.speakALot(); // since Person doesn't know anything about specific methods of derived classes compilation fails 

Student b = new Student();
b.speak(); // calling speak() method of student object
b.think(); // inheritance trick, child class keeps reference to its base class and that's why public and protected fields and methods are available
b.speakALot(); // calling speakALot() method of student object
Ibrokhim Kholmatov
  • 1,079
  • 2
  • 13
  • 16
  • thank you, you're giving a great explanation .. but I have a question, I'm studying java from javatpoint turorials, and from this link [static binding and dynamic binding](https://www.javatpoint.com/static-binding-and-dynamic-binding) I have understood that binding is the operation of connecting a method call to a method body, but I'm having some troubles understanding some cases, like in your example can you edit the answer to add the binding type for each method call? or even write that here. – Abd-Elrahman Adel Jan 05 '18 at 15:38
  • 1
    Have a look at this [tutorial](http://javaconceptoftheday.com/static-binding-and-dynamic-binding-in-java/) first. If you will have a question I'll update my answer – Ibrokhim Kholmatov Jan 05 '18 at 16:18
  • I believe this question will determine if I understood it right or not .. did that mean static and dynamic binding are steps (not options), and the both of them may happen in the same method call to determine the method body needs to be called?? – Abd-Elrahman Adel Jan 05 '18 at 16:58
  • 1
    To run app you must compile it first! There is no option to escape compilation. Compiler checks that method `think` exist in class `Person` but JVM knows that it has to call `think` method of `Person` class because it is not overridden in `Student` class. – Ibrokhim Kholmatov Jan 05 '18 at 18:14
  • You're awesome :) – Abd-Elrahman Adel Jan 05 '18 at 18:22
0

If I just write a general purpose class to test any kind of Vehicle as follows.

public class Workshop{
    public boolean test(Vehicle vehicle){
        vehicle.start();
        vehicle.stop();
        //...more code
        return true;
    }
 }

I can compile this code only with Vehicle type, though none of the child classes of Vehicle have been written. In general frameworks exploit this capability of providing processing based on generic type in absence of concrete types (clients are free to extend child class hierarchy). In such cases Compiler will just make sure that vehicle will have at least one implementation (null implementation like {} is also acceptable) will be available so as not to break the code.

Kedar Tokekar
  • 418
  • 3
  • 10