Static and Dynamic Binding in Java
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
| Bound at compile time (static) | Bound at runtime (dynamic) |
|---|---|
static methods | Instance 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
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());
}
}A bike
vehicle
Vehicle categoryHow it works
v.describe(): an overridable instance method, so dynamic binding. The object is aBike:"A bike".v.type: a field, so static binding to the declared typeVehicle:"vehicle".v.category(): a static method, so static binding toVehicle:"Vehicle category". The object isn't even consulted. WritingVehicle.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:
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;| Instruction | Used for | Binding |
|---|---|---|
invokestatic | Static methods | Static: the exact class and method are fixed |
invokespecial | Constructors, super.method() | Static: no lookup on the object's class |
invokevirtual | Instance methods on classes | Dynamic: looked up from the object's class |
invokeinterface | Methods called through an interface type | Dynamic |
getfield, getstatic | Reading fields | Static: 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
- Easy: For each line, say static or dynamic:
Math.max(2, 3);list.size();this.helper()wherehelperis private;account.balance;super.toString(). - Harder: Compile
Binding.java, runjavap -c Binding, then changev.category()toBike.category()and see which instruction and class change.
Key Takeaways
Was this tutorial helpful?