Действительно ли введение метода по умолчанию в интерфейс сохраняет обратную совместимость?

Я думаю, что я немного смущен введением методов по умолчанию для интерфейсов в Java. Насколько я понимаю, идея заключается в том, что методы по умолчанию могут быть введены в существующие интерфейсы, не нарушая существующий код.

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

Если я реализую два интерфейса, я, очевидно, должен реализовать объединение абстрактных методов, определенных в обоих интерфейсах. Я наследую реализацию всех методов по умолчанию; однако, если случается конфликт между методами по умолчанию в двух интерфейсах, я должен переопределить этот метод в своем реализующем классе.

Это звучит хорошо, но как насчет следующего сценария?

Предположим, есть интерфейс:

package com.example ;
/** 
* Version 1.0
*/
public interface A {
  public void foo() ;
  /**
  * The answer to life, the universe, and everything.
  */
  public default int getAnswer() { return 42 ;}
}

и второй интерфейс

package com.acme ;
/** 
* Version 1.0
*/
public interface B {
  public void bar() ;
}

Поэтому я могу написать следующее:

package com.mycompany ;
public class C implements com.example.A, com.acme.B {
  @Override
  public void foo() {
    System.out.println("foo");
  }
  @Override
  public void bar() {
    System.out.println("bar");
  }
  public static void main(String[] args) {
    System.out.println(new C().getAnswer());
  }
}

Так что должно быть хорошо, и действительно

java com.mycompany.C 

отображает результат 42.

Но теперь предположим, что acme.com вносит следующие изменения в B:

package com.acme ;
/** 
* Version 1.1
*/
public interface B {
  public void bar() ;
  /**
  * The answer to life, the universe, and everything
  * @since 1.1
  */
  public default int getAnswer() {
    return 6*9;
  }
}

Насколько я понимаю, внедрение этого метода должно быть безопасным. Но если я теперь запусту существующий com.mycompany.C с новой версией, я получу ошибку времени выполнения:

Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting default methods: com/example/A.getAnswer com/acme/B.getAnswer
at com.mycompany.C.getAnswer(C.java)
at com.mycompany.C.main(C.java:12)

Это не совсем удивительно, но разве это не означает, что введение методов по умолчанию в существующие интерфейсы всегда рискует сломать существующий код? Что мне не хватает?

Ответы на вопрос(2)

Ваш ответ на вопрос