Интерфейсы
Тема дорожной карты · Java
Интерфейсы Java определяют контракт — набор сигнатур методов, которые реализующие классы обязаны соблюдать, — и являются основным механизмом достижения абстракции, полиморфизма и слабой связанности в системе типов Java. До Java 8 интерфейсы могли содержать только public abstract-методы и константы public static final; Java 8 добавила default-методы (конкретные реализации с ключевым словом default) и статические фабричные методы, обеспечивая эволюцию API без нарушения обратной совместимости. Класс реализует один или несколько интерфейсов с помощью ключевого слова implements и должен предоставить конкретные реализации всех абстрактных методов, иначе сам класс должен быть объявлен abstract; это принудительно проверяется компилятором независимо от того, каким ClassLoader загружается класс. Интерфейсы Java занимают центральное место во всей экосистеме: Collections Framework построен на интерфейсах Iterable, Collection, List, Set, Map и Queue; JDBC использует интерфейсы Connection, Statement и ResultSet так, что любой производитель драйвера может предоставить реализации; а внедрение зависимостей Spring опирается на программирование через интерфейсы, чтобы Mockito мог генерировать динамические прокси для модульного тестирования. Когда интерфейс имеет ровно один абстрактный метод, он становится Functional Interface, позволяя использовать Lambda-выражения и ссылки на методы в качестве реализаций — Runnable, Callable<V>, Comparator<T> и Predicate<T> — все это Functional Interfaces, для которых Java-компилятор может подставить лаконичный синтаксис () -> ....
Как это работает
Интерфейсы в Java строится на классах, наследовании (extends), интерфейсах (implements), полиморфизме (override + динамическая диспетчеризация), инкапсуляции (private-поля + public-методы), композиции (предпочтительнее наследования). Современная Java добавляет records (immutable носители данных), sealed классы/интерфейсы (закрытые иерархии для pattern matching), default-методы интерфейсов (эволюция без слома implementers).
Когда применять
Композиция (класс has-a) лучше наследования (класс is-a) по умолчанию — Liskov substitution исключает многие "is-a", выглядящие интуитивно. Records — для immutable data-классов. Sealed-типы — когда иерархия конечна (Shape — это Circle, Square или Triangle). Избегайте глубоких иерархий (>2-3 уровней = сигнал плохого дизайна).
Типичные ошибки
Ловушки Интерфейсы: глубокие иерархии наследования, в которых "find usages" IDE не разберётся; mutable-поля без thread-safety на shared-объектах; override equals без hashCode (сломано в любом HashMap); toString сущности случайно выставляет колонку БД (утечка в логи); абстрактные базовые классы, смешивающие concern (разделяйте).