OOP

Java Static Binding Tutorial

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.

Related posts

Java Hidden Classes

Java sealed classes

Java Static Classes