ГлавнаяБлогextends и implements в Java: полное руководство
Собеседования

extends и implements в Java: полное руководство

Разбираем extends и implements в Java: чем отличаются, как работают, почему класс может реализовать много интерфейсов. Примеры кода и ответы на вопросы собеседований.

Al
Редакция Algolitalgolit.ru
10 мин чтения23 июля 2026 г.

В предыдущей статье мы разобрали, что такое интерфейс и почему он выступает контрактом между клиентом и поставщиком. Теперь пора понять одну из самых популярных тем на собеседованиях по Java: в чём разница между extends и implements? Может ли класс наследовать несколько классов? Может ли класс реализовать несколько интерфейсов? Почему методы интерфейса всегда public abstract? Почему переменные интерфейса всегда public static final? Эти концепции лежат в основе множественного наследования в Java и широко используются в таких фреймворках, как Spring Boot, Hibernate и Java Collections Framework.

Зачем нужны extends и implements?

Java поддерживает два вида наследования:

  • Наследование реализации (через классы)
  • Наследование контракта (через интерфейсы)

Чтобы их различать, Java предоставляет два ключевых слова: extends и implements.

extends vs implements

Ключевое слово extends используется при наследовании от класса или расширении другого интерфейса. Ключевое слово implements используется, когда класс предоставляет реализацию для интерфейса.

Ключевое словоИспользуется сНазначение
extendsКласс → Класс, Интерфейс → ИнтерфейсУнаследовать существующее поведение
implementsКласс → ИнтерфейсПредоставить реализацию контракта

Класс может расширить только один класс

Java не поддерживает множественное наследование классов.

class Employee {
    public void work() {
        System.out.println("Сотрудник работает.");
    }
}

class Manager extends Employee {
    // Manager наследует метод work()
}

Почему класс не может расширить несколько классов? Предположим, Java бы это разрешила:

class A {
    public void display() {
        System.out.println("Класс A");
    }
}
class B {
    public void display() {
        System.out.println("Класс B");
    }
}
class C extends A, B { // ❌ Ошибка
}

Это называется проблемой ромба (Diamond Problem). Чтобы избежать неоднозначности, Java позволяет классу расширять только один класс.

Класс может реализовать несколько интерфейсов

В отличие от классов, интерфейсы содержат только контракты, а не реализации. Поэтому неоднозначности нет.

interface PaymentService {
    void processPayment();
}

interface NotificationService {
    void sendNotification();
}

class OnlineOrderService implements PaymentService, NotificationService {
    @Override
    public void processPayment() {
        System.out.println("Платёж обработан.");
    }

    @Override
    public void sendNotification() {
        System.out.println("Уведомление отправлено.");
    }
}

Класс может расширить один класс и реализовать несколько интерфейсов

Java допускает комбинацию обоих ключевых слов.

interface PaymentService {
    void processPayment();
}

interface NotificationService {
    void sendNotification();
}

class Order {
    public void displayOrder() {
        System.out.println("Отображение заказа.");
    }
}

class OnlineOrder extends Order implements PaymentService, NotificationService {
    @Override
    public void processPayment() {
        System.out.println("Оплата завершена.");
    }

    @Override
    public void sendNotification() {
        System.out.println("Клиент уведомлён.");
    }
}

Это очень распространённый дизайн в корпоративных приложениях.

Интерфейс может расширять несколько интерфейсов

Интерфейсы поддерживают множественное наследование.

interface PaymentService {
    void processPayment();
}

interface NotificationService {
    void sendNotification();
}

interface OrderService extends PaymentService, NotificationService {
    // OrderService наследует оба метода
}

Допустимые синтаксические комбинации

ВыражениеДопустимо?Объяснение
class B extends AКласс наследует другой класс
interface B extends AИнтерфейс расширяет интерфейс
class C implements AКласс реализует интерфейс
class C extends A implements BРасширить один класс и реализовать интерфейсы
interface C extends A, BИнтерфейс расширяет несколько интерфейсов
class C implements A extends BНеверный синтаксис

Методы интерфейса

Каждый метод, объявленный внутри интерфейса, неявно является public и abstract. Следующие объявления эквивалентны:

interface PaymentService {
    void processPayment();
}

// Компилятор добавляет public abstract
interface PaymentService {
    public abstract void processPayment();
}

Почему методы интерфейса public? Интерфейсы представляют контракты. Любой реализующий класс, независимо от пакета, должен иметь доступ к этим методам. Почему abstract? Интерфейсы определяют что должно произойти, а реализующие классы — как это происходит.

Недопустимые модификаторы для традиционных абстрактных методов интерфейса: private, protected, final, synchronized, native. Например:

interface PaymentService {
    final void processPayment(); // ❌ Ошибка компиляции
}

Примечание: начиная с Java 8, интерфейсы могут содержать default и static методы, а с Java 9 — private методы. В этой статье мы сосредоточились на традиционных абстрактных методах.

Переменные интерфейса

Интерфейсы могут содержать переменные, но каждая переменная интерфейса неявно является public static final.

interface ApplicationConstants {
    int MAX_USERS = 100;
}

// Компилятор обрабатывает как:
// public static final int MAX_USERS = 100;

Почему public? Каждый реализующий класс должен иметь доступ к константе. Почему static? Значение принадлежит самому интерфейсу, объект не требуется. Почему final? Значение никогда не должно меняться, реализующие классы не могут его изменить.

Переменные интерфейса должны быть инициализированы. Неправильно:

interface ApplicationConstants {
    int MAX_USERS; // ❌ Ошибка: = expected
}

Правильно:

interface ApplicationConstants {
    int MAX_USERS = 100;
}

Переменные интерфейса нельзя изменить.

interface ApplicationConstants {
    int MAX_USERS = 100;
}

class Test implements ApplicationConstants {
    public static void main(String[] args) {
        // MAX_USERS = 200; ❌ Ошибка компиляции
        System.out.println(MAX_USERS); // 100
    }
}

Частые ошибки новичков

  1. Попытка расширить несколько классов: class C extends A, B {} — Java не позволяет.
  2. Забыть реализовать все методы интерфейса: каждый абстрактный метод должен быть реализован, если класс не абстрактный.
  3. Попытка изменить переменную интерфейса: MAX_USERS = 500; — ошибка компиляции, так как переменная final.
  4. Думать, что переменные интерфейса — экземплярные: они static, обращайтесь через имя интерфейса: ApplicationConstants.MAX_USERS.

Лучшие практики

  • Используйте extends только для наследования между связанными классами.
  • Предпочитайте интерфейсы для определения поведения и контрактов.
  • Ограничьте переменные интерфейса только настоящими константами.
  • Избегайте хранения изменяемого состояния в интерфейсах.
  • Используйте осмысленные имена интерфейсов, например PaymentService, NotificationService, OrderRepository.

Вопросы на собеседовании

  1. В чём разница между extends и implements? extends используется для наследования, implements — для предоставления реализации интерфейса.
  2. Может ли класс расширить несколько классов? Нет, Java предотвращает множественное наследование классов, чтобы избежать неоднозначности.
  3. Может ли класс реализовать несколько интерфейсов? Да, класс может реализовать любое количество интерфейсов.
  4. Может ли интерфейс расширять несколько интерфейсов? Да, это способ Java поддерживать множественное наследование типов.
  5. Почему методы интерфейса public abstract? Потому что интерфейсы определяют общедоступные контракты, которые должны быть реализованы.
  6. Почему переменные интерфейса public static final? Они представляют общие константы, принадлежащие интерфейсу, и не могут быть изменены.
  7. Почему переменные интерфейса должны быть инициализированы? Потому что они final, а final-переменные должны получить значение ровно один раз.

Быстрый мнемонический приём 🧠

Запомните EIM:

  • E → Extends → Один класс
  • I → Implements → Много интерфейсов
  • M → Multiple Interface Inheritance (множественное наследование интерфейсов)

Думайте EIM, когда видите наследование в Java.

Ключевые выводы

  • extends используется для наследования классов и интерфейсов.
  • implements используется, когда класс реализует интерфейс.
  • Класс может расширить только один класс.
  • Класс может реализовать несколько интерфейсов.
  • Интерфейс может расширять несколько интерфейсов.
  • Методы интерфейса неявно public abstract.
  • Переменные интерфейса неявно public static final.
  • Константы интерфейса должны быть инициализированы при объявлении.

Если это руководство было полезным, поставьте ❤️ и подпишитесь для получения новых уроков по Java, вопросов с собеседований и практических примеров кода. Удачи в программировании!

#extends#implements#наследование в Java#интерфейсы Java#собеседование Java
Al
Редакция Algolit

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

Хочешь закрепить знания на практике?

Решай задачи на Algolit — интерактивная платформа для обучения

Начать бесплатно →