Почему интерфейс Collection в Java не был сделан абстрактным классом?

«Почему интерфейс Collection в Java не был сделан абстрактным классом?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Использование интерфейса вместо абстрактного класса для Collection — это осознанное и правильное архитектурное решение, основанное на принципах гибкости и слабой связанности.

Ключевые причины:

  1. Множественное «наследование»: Класс в Java может реализовать множество интерфейсов, но унаследоваться только от одного класса. Если бы Collection был абстрактным классом, разработчик не смог бы создать коллекцию, которая также является, например, Cloneable и Serializable от другого класса-родителя.

    // Невозможно, если Collection — класс:
    class MyCollection extends SomeFrameworkClass implements Collection, Serializable, Cloneable { ... }
    // Возможно, так как Collection — интерфейс:
    class MyCollection extends SomeFrameworkClass implements Collection<java.io.Serializable>, Cloneable { ... }
  2. Чистый контракт, а не реализация: Интерфейс определяет что должна делать коллекция (методы add, remove, size), но не навязывает как это делать. Абстрактный класс часто содержит частичную реализацию, что ограничивает свободу разработчика структурой наследования.

  3. Эволюция API: Начиная с Java 8, интерфейсы могут содержать реализации методов по умолчанию (default-методы). Это позволило добавлять новую функциональность (например, stream(), removeIf) в интерфейс Collection, не ломая существующие реализации, — что было бы невозможно с абстрактным классом, не нарушая наследование.

Итог: Интерфейс Collection обеспечивает максимальную гибкость, позволяя определять контракт для любой иерархии классов, что является фундаментом для полиморфизма в Java Collections Framework.