В чем разница между статическим и динамическим связыванием (binding) в Java?

«В чем разница между статическим и динамическим связыванием (binding) в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Статическое связывание (раннее) происходит во время компиляции. Вызываемый метод определяется по типу ссылочной переменной. Динамическое связывание (позднее) происходит во время выполнения (Runtime). Вызываемый метод определяется по фактическому типу объекта.

Пример, демонстрирующий разницу:

class Animal {
    void sound() { System.out.println("Animal sound"); } // Будет переопределен
    static void describe() { System.out.println("An animal"); } // Статический
}

class Dog extends Animal {
    @Override
    void sound() { System.out.println("Bark"); } // Динамическое связывание
    static void describe() { System.out.println("A dog"); } // Сокрытие метода (статическое)
}

public class Test {
    public static void main(String[] args) {
        Animal myDog = new Dog(); // Тип ссылки: Animal, тип объекта: Dog

        // ДИНАМИЧЕСКОЕ СВЯЗЫВАНИЕ (для переопределенных методов)
        myDog.sound(); // Вывод: "Bark" (вызван метод из Dog)

        // СТАТИЧЕСКОЕ СВЯЗЫВАНИЕ (для static, final, private методов и перегрузки)
        myDog.describe(); // Вывод: "An animal" (вызван метод из Animal, по типу ссылки)
        Dog.describe(); // Вывод: "A dog"
    }
}

Правила:

  • Динамическое связывание применяется для переопределенных (@Override) методов экземпляра.
  • Статическое связывание применяется для:
    1. Статических методов.
    2. Финальных (final) методов.
    3. Приватных (private) методов.
    4. Перегруженных (overloaded) методов.