Static and Dynamic Binding in Java

Naveen AnamaneniUpdated · 5 min read

Every method call and field access in your code has to be linked to the actual code or memory it refers to. That linking is called binding. If it's settled while compiling, it's static binding (early binding). If the final decision waits for the running program, it's dynamic binding (late binding). This lesson pulls together what the last few lessons showed into one rule you can apply to any line of code.

The Rule

The compiler binds most things; overridable instance methods wait for the object
Bound at compile time (static)Bound at runtime (dynamic)
static methodsInstance methods that can be overridden
private methods
final methods (one version only)
Constructors and super.method() calls
Fields (static and instance)
The choice between overloads

Seeing Both in One Program

Binding.java▶ Try it
public class Binding {
    static class Vehicle {
        String type = "vehicle";
        static String category() { return "Vehicle category"; }
        String describe() { return "A vehicle"; }
    }
 
    static class Bike extends Vehicle {
        String type = "bike";
        static String category() { return "Bike category"; }
        @Override String describe() { return "A bike"; }
    }
 
    public static void main(String[] args) {
        Vehicle v = new Bike();
        System.out.println(v.describe());
        System.out.println(v.type);
        System.out.println(v.category());
    }
}
Output
A bike
vehicle
Vehicle category

How it works

  1. v.describe(): an overridable instance method, so dynamic binding. The object is a Bike: "A bike".
  2. v.type: a field, so static binding to the declared type Vehicle: "vehicle".
  3. v.category(): a static method, so static binding to Vehicle: "Vehicle category". The object isn't even consulted. Writing Vehicle.category() makes that honest.

Common Mistakes

Saying "all method calls are dynamic in Java". Static, private and final methods, constructors and super calls aren't.

Calling static methods through instances. It hides the fact that the object is ignored; use the class name.

Redeclaring fields in subclasses and expecting them to override. Fields are statically bound.

Under the Hood

The bytecode instruction tells you which kind of binding each call uses:

javap -c Binding (trimmed)
         0: new           #7                  // class Binding$Bike
        12: invokevirtual #16                 // Method Binding$Vehicle.describe:()Ljava/lang/String;
        22: getfield      #28                 // Field Binding$Vehicle.type:Ljava/lang/String;
        33: invokestatic  #32                 // Method Binding$Vehicle.category:()Ljava/lang/String;
InstructionUsed forBinding
invokestaticStatic methodsStatic: the exact class and method are fixed
invokespecialConstructors, super.method()Static: no lookup on the object's class
invokevirtualInstance methods on classesDynamic: looked up from the object's class
invokeinterfaceMethods called through an interface typeDynamic
getfield, getstaticReading fieldsStatic: the field is fixed to the declared class

Notice getfield ... Binding$Vehicle.type: the field is fixed to Vehicle, which is why the Bike object's own type is never read.

Interview Corner

What is the difference between static and dynamic binding?

Static binding links a call to its target at compile time using the declared type; it applies to static, private and final methods, constructors, super calls, fields and the choice of overload. Dynamic binding links a call at runtime using the object's actual class; it applies to overridable instance methods and is what makes overriding and runtime polymorphism work. In bytecode, invokestatic and invokespecial are statically bound, while invokevirtual and invokeinterface are dispatched dynamically.

Is overloading static or dynamic binding?

The choice of overload is static: the compiler picks the signature from the declared argument types. If the chosen method is an overridable instance method, which implementation of that signature runs is still decided dynamically.

Practice

  1. Easy: For each line, say static or dynamic: Math.max(2, 3); list.size(); this.helper() where helper is private; account.balance; super.toString().
  2. Harder: Compile Binding.java, run javap -c Binding, then change v.category() to Bike.category() and see which instruction and class change.

Quick check: Static and dynamic binding

4 questions
1Which is bound dynamically?
2Vehicle v = new Bike(); v.type reads:
3Which instruction is used for super.describe()?
4Another name for dynamic binding is:

Key Takeaways

Was this tutorial helpful?

Lesson 130 of 482