Абстрактные классы

Тема дорожной карты · Java

Абстрактные классы в Java — это частичные реализации, которые нельзя непосредственно инстанциировать; они служат чертежами для конкретных подклассов в иерархии классов. Объявленный с ключевым словом abstract, абстрактный класс может сочетать полностью реализованные методы с объявлениями abstract-методов, которые подклассы обязаны переопределить, что делает их незаменимыми для соблюдения контрактов при совместном использовании повторно используемой логики в объектно-ориентированном проектировании. В отличие от Java Interfaces, абстрактные классы могут содержать поля экземпляра, конструкторы и static-утилитные методы, позволяя централизовать общее состояние вместе с поведением. JVM предотвращает инстанциирование абстрактного класса на уровне байткода, поэтому любая попытка вызвать new AbstractShape() приведёт к ошибке компиляции, подкрепляя замысел проектировщика. Абстрактные классы широко используются в фреймворках Spring и Hibernate — например, AbstractApplicationContext предоставляет управление жизненным циклом, оставляя refreshBeanFactory() абстрактным для конкретных реализаций контейнеров.

Как это работает

Абстрактные классы в 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 (разделяйте).

Связанные понятия

Полезные ресурсы