Static Binding (also known as early binding) refers to the process in which the method or variable to be executed is determined at compile time. In Java, static binding occurs for methods and variables that are resolved at compile time, such as static methods, private methods, and final methods. Static binding is the opposite of dynamic binding (late binding), which occurs at runtime.
In this tutorial, we will explore static binding with code examples and cover how it works in Java.
1. What is Static Binding?
In static binding, the compiler determines which method or variable to call at compile time, based on the type of reference rather than the actual object. This is typically applied to:
Static methods: Because they are associated with the class, not instances.
Private methods: Because they cannot be overridden.
Final methods: Since they cannot be overridden.
Member variables: Which are resolved based on the reference type, not the object type.
2. Static vs Dynamic Binding
Static Binding: Method or variable is determined at compile time based on the reference type.
Dynamic Binding: Method is determined at runtime based on the actual object.
3. Static Binding with Static Methods
Static methods are resolved at compile time because they belong to the class, not to a specific instance of the class. Therefore, method calls involving static methods use static binding.
Example of Static Binding with Static Methods:
class Parent { // Static method in the parent class public static void display() { System.out.println("Static method in Parent class"); } } class Child extends Parent { // Static method in the child class public static void display() { System.out.println("Static method in Child class"); } } public class StaticBindingExample { public static void main(String[] args) { Parent parent = new Parent(); Parent child = new Child(); // Static methods are bound at compile time, based on reference type parent.display(); // Static method in Parent class child.display(); // Static method in Parent class (not Child class) } }
Explanation:
Static methods are bound based on the reference type (Parent), so both calls invoke the Parent class's display() method, even though the child reference points to a Child object.
Output:
Static method in Parent class Static method in Parent class
4. Static Binding with Private Methods
Private methods are not inherited and cannot be overridden, so they are also resolved at compile time using static binding.
Example of Static Binding with Private Methods:
class Parent { // Private method in Parent class private void display() { System.out.println("Private method in Parent class"); } public void callDisplay() { display(); // Calls Parent's private method } } class Child extends Parent { // This method is not overriding the Parent's method, it's a separate method private void display() { System.out.println("Private method in Child class"); } } public class StaticBindingPrivateMethodExample { public static void main(String[] args) { Parent parent = new Parent(); Parent child = new Child(); // Private methods are resolved at compile time, based on reference type parent.callDisplay(); // Private method in Parent class child.callDisplay(); // Private method in Parent class } }
Explanation:
The display() method is private in both Parent and Child. However, the callDisplay() method always calls the Parent class's private method because private methods are statically bound at compile time.
Output:
Private method in Parent class Private method in Parent class
5. Static Binding with Final Methods
Final methods cannot be overridden, so method calls to final methods are resolved at compile time, using static binding.
Example of Static Binding with Final Methods:
class Parent { // Final method in Parent class public final void show() { System.out.println("Final method in Parent class"); } } class Child extends Parent { // This method cannot override the Parent class's final method public void display() { System.out.println("Display method in Child class"); } } public class StaticBindingFinalMethodExample { public static void main(String[] args) { Parent parent = new Parent(); Parent child = new Child(); // Final methods are bound at compile time, based on reference type parent.show(); // Final method in Parent class child.show(); // Final method in Parent class } }
Explanation:
The show() method in the Parent class is final, so it cannot be overridden in the Child class. The method is resolved at compile time.
Output:
Final method in Parent class Final method in Parent class
6. Static Binding with Variables
Variables (both static and non-static) are resolved based on the reference type, not the object type. This means variable references are statically bound at compile time.
Example of Static Binding with Variables:
class Parent { // Static variable public static String staticVar = "Static variable in Parent"; // Instance variable public String instanceVar = "Instance variable in Parent"; } class Child extends Parent { // Static variable public static String staticVar = "Static variable in Child"; // Instance variable public String instanceVar = "Instance variable in Child"; } public class StaticBindingVariablesExample { public static void main(String[] args) { Parent parent = new Parent(); Parent child = new Child(); // Static and instance variables are bound at compile time based on reference type System.out.println(parent.staticVar); // Static variable in Parent System.out.println(child.staticVar); // Static variable in Parent System.out.println(parent.instanceVar); // Instance variable in Parent System.out.println(child.instanceVar); // Instance variable in Parent } }
Explanation:
Both staticVar and instanceVar are resolved based on the reference type (Parent), so even though child is pointing to a Child object, it still resolves to the variables in Parent.
Output:
Static variable in Parent Static variable in Parent Instance variable in Parent Instance variable in Parent
7. Static Binding with Method Overloading
Method overloading in Java is resolved at compile time, meaning overloaded methods are statically bound.
Example of Static Binding with Method Overloading:
class Calculator { // Method to add two integers public int add(int a, int b) { return a + b; } // Overloaded method to add three integers public int add(int a, int b, int c) { return a + b + c; } } public class StaticBindingOverloadingExample { public static void main(String[] args) { Calculator calculator = new Calculator(); // Method overloading is resolved at compile time (static binding) int result1 = calculator.add(10, 20); // Calls method with 2 parameters int result2 = calculator.add(10, 20, 30); // Calls method with 3 parameters System.out.println("Result1: " + result1); // 30 System.out.println("Result2: " + result2); // 60 } }
Explanation:
Method overloading is an example of static binding where the method to be executed is determined at compile time based on the method signature (parameter types and count).
Output:
Result1: 30 Result2: 60
8. Static Binding with Static Blocks
Static blocks in Java are also resolved using static binding since they are executed at class loading time.
Example of Static Binding with Static Blocks:
class StaticBlockExample { // Static block static { System.out.println("Static block is executed"); } public static void display() { System.out.println("Static method is executed"); } } public class StaticBindingBlockExample { public static void main(String[] args) { // Static block and method are bound at compile time StaticBlockExample.display(); // Static block is executed (executed first), then Static method is executed } }
Explanation:
Static blocks and static methods are both bound at compile time and executed when the class is loaded or when the method is invoked.
Output:
Static block is executed Static method is executed
Conclusion
Static Binding in Java refers to the compile-time resolution of methods, variables, and static blocks. Static binding is applied to:
Static methods: Since they belong to the class rather than an object, they are resolved at compile time.
Private methods: As they cannot be overridden, they are bound to the class at compile time.
Final methods: These methods cannot be overridden, so they are resolved at compile time.
Variables: Both static and instance variables are resolved based on the reference type rather than the object type.
In contrast to dynamic binding, static binding ensures that method or variable calls are determined at compile time, providing predictability in how methods and variables are resolved. Understanding static binding helps in writing more predictable and efficient code, particularly when working with inheritance, method overriding, and polymorphism.