В чем разница объектно ориентированного и функционального программирования
Что проверяют
Понимаете ли вы парадигмы как способ организовать код, а не как список модных слов. Следом обычно просят показать, где в Java-проекте вы используете функциональный стиль и где он вредит.
Как отвечать
Суть различия: ООП объединяет данные и поведение в объекте и управляет изменяемым состоянием через инкапсуляцию. ФП разделяет данные и функции, строит программу из преобразований неизменяемых значений и выносит побочные эффекты на край системы.
- ООП: инкапсуляция, полиморфизм через интерфейсы, наследование как частный и не самый любимый случай. Сильная сторона: легко добавить новый тип, реализовав интерфейс;
- ФП: чистые функции, неизменяемость, функции высшего порядка, композиция. Сильная сторона: легко добавить новую операцию над существующими данными и проще рассуждать о многопоточности;
- ФП в Java: лямбды и
StreamAPI с Java 8,FunctionсandThenиcompose,Optional, неизменяемыеList.ofиStream.toList(),recordдля значений. С Java 21 связка sealed-иерархий и pattern matching вswitchдаёт аналог алгебраических типов.
Сильный ответ показывает, что Java мультипарадигменная и парадигмы обычно смешивают: сервисы и границы модулей строятся объектно, а бизнес-правила и обработка коллекций внутри пишутся как чистые функции над record. Такой код легко тестировать без моков.
Можно упомянуть и ограничения: в Java нет оптимизации хвостовой рекурсии, а лямбда захватывает только effectively final переменные.
Где спотыкаются
Говорят «в ФП нет состояния». Состояние есть, просто оно явное: новая версия данных возвращается из функции, а не меняется на месте.
Считают, что лямбда в коде уже делает его функциональным. forEach, который складывает результаты во внешний ArrayList, это императивный код в функциональной обёртке.
Запускают parallelStream() с общим изменяемым состоянием и получают гонку. Параллельный стрим безопасен, только когда операции чистые и без побочных эффектов.