Каковы ключевые различия между интерфейсом и абстрактным классом в Java?

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

Ответ

Основные различия выходят за рамки синтаксиса наследования:

Критерий Интерфейс (до Java 8+) Абстрактный класс
Состояние Только static final константы Может содержать любые поля (состояние объекта)
Конструкторы Не может иметь Может иметь конструкторы (для инициализации состояния)
Модификаторы методов Неявно publicabstract до Java 8) Любые (protected, private и т.д.)
Реализация по умолчанию default и static методы (с Java 8) Полностью реализованные методы
Наследование Класс может реализовать много интерфейсов Класс может наследовать только один абстрактный класс

Пример:

// Интерфейс определяет контракт
interface Loggable {
    String LOG_PREFIX = "LOG:"; // Константа
    void log(); // Абстрактный метод (неявно public)
    default void printTimestamp() { // Реализация по умолчанию
        System.out.println("Time: " + Instant.now());
    }
}

// Абстрактный класс может содержать состояние и общую логику
abstract class Shape {
    protected String color; // Поле с состоянием
    public Shape(String color) { this.color = color; } // Конструктор
    abstract double area(); // Абстрактный метод
    public String getColor() { return color; } // Реализованный метод
}

Когда что использовать:

  • Интерфейс: Для определения контракта (возможности), который могут реализовать несвязанные классы.
  • Абстрактный класс: Для предоставления общей базы с частичной реализацией классам с общим состоянием и поведением.