Static Vs. Dynamic Binding in Java
Solution 1
From Javarevisited blog post:
Here are a few important differences between static and dynamic binding:
- Static binding in Java occurs during compile time while dynamic binding occurs during runtime.
private
,final
andstatic
methods and variables use static binding and are bonded by compiler while virtual methods are bonded during runtime based upon runtime object.- Static binding uses
Type
(class
in Java) information for binding while dynamic binding uses object to resolve binding.- Overloaded methods are bonded using static binding while overridden methods are bonded using dynamic binding at runtime.
Here is an example which will help you to understand both static and dynamic binding in Java.
Static Binding Example in Java
public class StaticBindingTest { public static void main(String args[]) { Collection c = new HashSet(); StaticBindingTest et = new StaticBindingTest(); et.sort(c); } //overloaded method takes Collection argument public Collection sort(Collection c) { System.out.println("Inside Collection sort method"); return c; } //another overloaded method which takes HashSet argument which is sub class public Collection sort(HashSet hs) { System.out.println("Inside HashSet sort method"); return hs; } }
Output: Inside Collection sort method
Example of Dynamic Binding in Java
public class DynamicBindingTest { public static void main(String args[]) { Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car vehicle.start(); //Car's start called because start() is overridden method } } class Vehicle { public void start() { System.out.println("Inside start method of Vehicle"); } } class Car extends Vehicle { @Override public void start() { System.out.println("Inside start method of Car"); } }
Output: Inside start method of Car
Solution 2
Connecting a method call to the method body is known as Binding. As Maulik said "Static binding uses Type(Class in Java) information for binding while Dynamic binding uses Object to resolve binding." So this code :
public class Animal {
void eat() {
System.out.println("animal is eating...");
}
}
class Dog extends Animal {
public static void main(String args[]) {
Animal a = new Dog();
a.eat(); // prints >> dog is eating...
}
@Override
void eat() {
System.out.println("dog is eating...");
}
}
Will produce the result: dog is eating... because it is using the object reference to find which method to use. If we change the above code to this:
class Animal {
static void eat() {
System.out.println("animal is eating...");
}
}
class Dog extends Animal {
public static void main(String args[]) {
Animal a = new Dog();
a.eat(); // prints >> animal is eating...
}
static void eat() {
System.out.println("dog is eating...");
}
}
It will produce : animal is eating... because it is a static method, so it is using Type (in this case Animal) to resolve which static method to call. Beside static methods private and final methods use the same approach.
Solution 3
Well in order to understand how static and dynamic binding actually works? or how they are identified by compiler and JVM?
Let's take below example where Mammal
is a parent class which has a method speak()
and Human
class extends Mammal
, overrides the speak()
method and then again overloads it with speak(String language)
.
public class OverridingInternalExample {
private static class Mammal {
public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}
private static class Human extends Mammal {
@Override
public void speak() { System.out.println("Hello"); }
// Valid overload of speak
public void speak(String language) {
if (language.equals("Hindi")) System.out.println("Namaste");
else System.out.println("Hello");
}
@Override
public String toString() { return "Human Class"; }
}
// Code below contains the output and bytecode of the method calls
public static void main(String[] args) {
Mammal anyMammal = new Mammal();
anyMammal.speak(); // Output - ohlllalalalalalaoaoaoa
// 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Mammal humanMammal = new Human();
humanMammal.speak(); // Output - Hello
// 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Human human = new Human();
human.speak(); // Output - Hello
// 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V
human.speak("Hindi"); // Output - Namaste
// 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V
}
}
When we compile the above code and try to look at the bytecode using javap -verbose OverridingInternalExample
, we can see that compiler generates a constant table where it assigns integer codes to every method call and byte code for the program which I have extracted and included in the program itself (see the comments below every method call)
By looking at above code we can see that the bytecodes of humanMammal.speak()
, human.speak()
and human.speak("Hindi")
are totally different (invokevirtual #4
, invokevirtual #7
, invokevirtual #9
) because the compiler is able to differentiate between them based on the argument list and class reference. Because all of this get resolved at compile time statically that is why Method Overloading is known as Static Polymorphism or Static Binding.
But bytecode for anyMammal.speak()
and humanMammal.speak()
is same (invokevirtual #4
) because according to compiler both methods are called on Mammal
reference.
So now the question comes if both method calls have same bytecode then how does JVM know which method to call?
Well, the answer is hidden in the bytecode itself and it is invokevirtual
instruction set. JVM uses the invokevirtual
instruction to invoke Java equivalent of the C++ virtual methods. In C++ if we want to override one method in another class we need to declare it as virtual, But in Java, all methods are virtual by default because we can override every method in the child class (except private, final and static methods).
In Java, every reference variable holds two hidden pointers
- A pointer to a table which again holds methods of the object and a pointer to the Class object. e.g. [speak(), speak(String) Class object]
- A pointer to the memory allocated on the heap for that object’s data e.g. values of instance variables.
So all object references indirectly hold a reference to a table which holds all the method references of that object. Java has borrowed this concept from C++ and this table is known as virtual table (vtable).
A vtable is an array like structure which holds virtual method names and their references on array indices. JVM creates only one vtable per class when it loads the class into memory.
So whenever JVM encounter with a invokevirtual
instruction set, it checks the vtable of that class for the method reference and invokes the specific method which in our case is the method from a object not the reference.
Because all of this get resolved at runtime only and at runtime JVM gets to know which method to invoke, that is why Method Overriding is known as Dynamic Polymorphism or simply Polymorphism or Dynamic Binding.
You can read it more details on my article How Does JVM Handle Method Overloading and Overriding Internally.
Solution 4
The compiler only knows that the type of "a" is Animal
; this happens at compile time, because of which it is called static binding (Method overloading). But if it is dynamic binding then it would call the Dog
class method. Here is an example of dynamic binding.
public class DynamicBindingTest {
public static void main(String args[]) {
Animal a= new Dog(); //here Type is Animal but object will be Dog
a.eat(); //Dog's eat called because eat() is overridden method
}
}
class Animal {
public void eat() {
System.out.println("Inside eat method of Animal");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("Inside eat method of Dog");
}
}
Output: Inside eat method of Dog
Solution 5
There are three major differences between static and dynamic binding while designing the compilers and how variables and procedures are transferred to the runtime environment. These differences are as follows:
Static Binding: In static binding three following problems are discussed:
Definition of a procedure
Declaration of a name(variable, etc.)
Scope of the declaration
Dynamic Binding: Three problems that come across in the dynamic binding are as following:
Activation of a procedure
Binding of a name
Lifetime of a binding
Related videos on Youtube
user2309750
Updated on April 12, 2020Comments
-
user2309750 about 4 years
I'm currently doing an assignment for one of my classes, and in it, I have to give examples, using Java syntax, of static and dynamic binding.
I understand the basic concept, that static binding happens at compile time and dynamic binding happens at runtime, but I can't figure out how they actually work specifically.
I found an example of static binding online that gives this example:
public static void callEat(Animal animal) { System.out.println("Animal is eating"); } public static void callEat(Dog dog) { System.out.println("Dog is eating"); } public static void main(String args[]) { Animal a = new Dog(); callEat(a); }
And that this would print "animal is eating" because the call to
callEat
uses static binding, but I'm unsure as to why this is considered static binding.So far none of the sources I've seen have managed to explain this in a way that I can follow.
-
William Gaul over 10 years
-
Hot Licks over 10 yearsNote that there are several different concepts that are referred to as "binding". In this particular case, for this type of binding (which involves a choice between similar but not identical method "signatures") the compiler (which makes "static" decisions, since they do not vary at run time) decides that the parameter is an "Animal" because that is the (static) type of the variable "a".
-
Hot Licks over 10 years(There are languages where the choice of the specific method signature would be left until runtime, and callEat(Dog) would be selected.)
-
-
Hot Licks over 10 yearsNot true. The compiler would make the exact same decision if you were doing a call on an interface.
-
Aaron over 10 years@HotLicks Exact same decision as what? If you compile a class to invoke a foo(String str) method on an interface, the compiler cannot know at compile time what class the foo(String str) method should be invoked upon. Only at runtime can the method invocation be bound to a particular class implementation.
-
Hot Licks over 10 yearsBut static binding to the specific method signature still would occur. The compiler would still pick callEat(Animal) over callEat(Dog).
-
Aaron over 10 years@HotLicks Sure, but that's not the question I answered. Perhaps it was misleading of me :D I compared it to invoking on an interface to highlight that at compile time the compiler cannot know whether you actually instantiated a different subclass/implementation or not.
-
Hot Licks over 10 yearsActually, at compile time the compiler can (in this case) very easily could know that "a" is a Dog. In fact, it likely has to go to some lengths to "forget" that.
-
Aaron over 10 years@HotLicks could do, but shouldn't. At least, I think i'd get very confused if the same invocation using the same object yielded different results in different places.
-
Gopal Gopi over 9 yearsand is from javarevisited.blogspot.in/2012/03/…
-
technazi over 7 yearsI still don't understand the difference,
-
Amnor over 7 yearsWouldn't this throw a compilation error such as "Cannot reference a non-static class/method from a static context"? I'm always confused with that, having in mind that main is static. Thanks in advance.
-
Mark about 7 years@technazi static binding just looks at the type (what ever is before the equals e.g Collection c = new HashSet(); so it will be seen as just a collection object when infact it is a hashset). Dyanmic binding takes into account the actual object (whats after the equals so it actually recognises its a HashSet).
-
Minh Nghĩa almost 4 yearsWhy can't Java deduce that
a
is actually aDog
at compile time? -
Deekshith Anand over 2 yearsVery good example. But I am confused with this scenario. Lets say StaticBindingTestChild extends StaticBindingTest and overrided botht the overloaded methods. Now if we do something like this: Collection c = new HashSet(); StaticBindingTest et = new StaticBindingTestChild(); et.sort(c); will it be static or dynamic binding?
-
Kim Mens over 2 yearsFor another discussion and example on what late or dynamic binding is you may also want to look at this question: stackoverflow.com/questions/19098459/…