Карта / ООП / Перегрузка и переопределение

Перегрузка и переопределение

Это два разных слова, которые легко перепутать — но они про совершенно разные вещи.

Перегрузка (overload) — несколько методов с одним именем, но разными параметрами, в одном классе:

void print(String s) { ... }
void print(int n) { ... }
void print(String s, int n) { ... }

Java сама выбирает нужную версию по тому, что ты передал при вызове. Подробнее — в теме «Перегрузка».

Переопределение (override) — наследник заменяет поведение метода родителя, оставляя ту же сигнатуру:

class Animal {
    void makeSound() { System.out.println("..."); }
}
class Dog extends Animal {
    @Override
    void makeSound() { System.out.println("Гав!"); }   // заменили поведение
}

@Override — не обязателен формально, но всегда пиши его: если опечатался в имени метода, компилятор сразу подскажет ошибку, а не тихо создаст новый метод вместо переопределения.

Копнуть глубже

Главное отличие на уровне момента принятия решения:

ПерегрузкаПереопределение
Гдев одном классеродитель → наследник
Что меняетсяпараметрытело метода
Когда выбираетсяна этапе компиляциина этапе выполнения
Сигнатураразнаята же

Переопределяемый метод должен иметь точно такие же параметры и совместимый тип возврата — иначе это случайно станет перегрузкой, а не переопределением (классическая ошибка новичка).

Под капотом

Перегрузка решается статически — компилятор смотрит на типы аргументов в момент компиляции и сразу “зашивает” в байт-код вызов конкретного метода.

Переопределение решается динамически — через виртуальную таблицу методов (vtable) объекта в рантайме. JVM смотрит на реальный класс объекта (не тип переменной) и вызывает версию метода именно этого класса. Это и есть полиморфизм в действии — подробнее в теме «Принципы ООП».

🎤 Закрыл тему, если можешь объяснить:
• разницу между перегрузкой и переопределением;
• почему перегрузка решается на компиляции, а переопределение — в рантайме (если дошёл до 2-го слоя).