Что произойдет, если класс в Java реализует два интерфейса с default-методами одинаковой сигнатуры?

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

Ответ

Возникнет конфликт компиляции. Компилятор Java потребует явного разрешения этой неоднозначности в классе-реализации.

Правило: Если класс реализует несколько интерфейсов, и более чем один из них предоставляет default-метод с одинаковой сигнатурой (имя и параметры), класс должен переопределить этот метод.

Способы разрешения конфликта в классе:

  1. Предоставить собственную реализацию.
  2. Явно указать, реализацию какого интерфейса использовать, используя синтаксис InterfaceName.super.methodName().

Пример:

interface PrinterA {
    default void print() {
        System.out.println("Print from A");
    }
}

interface PrinterB {
    default void print() {
        System.out.println("Print from B");
    }
}

// Класс ДОЛЖЕН переопределить `print`
class MultiPrinter implements PrinterA, PrinterB {

    // Способ 1: Своя реализация
    // @Override
    // public void print() {
    //     System.out.println("Custom print");
    // }

    // Способ 2: Выбрать реализацию PrinterA
    @Override
    public void print() {
        PrinterA.super.print(); // Явный вызов default-метода из PrinterA
    }
}

public class Main {
    public static void main(String[] args) {
        new MultiPrinter().print(); // Вывод: Print from A
    }
}

Важно: Если интерфейсы находятся в иерархии наследования (один наследует от другого), то побеждает метод из более специфичного интерфейса, и конфликта не возникает.