Does introducing a default method to an interface really preserve back-compatibility?

Although adding a default method with the same name in the two interfaces would make the code fail to compile, but once you resolve the compilation error, the binaries obtained after compiling both the interfaces, and the class implementing the interfaces, would be backward compatible.

So, the compatibility is really about binary compatibility. This is being explained in JLS §13.5.6 – Interface Method Declarations:

Adding a default method, or changing a method from abstract to
default, does not break compatibility with pre-existing binaries, but
may cause an IncompatibleClassChangeError if a pre-existing binary
attempts to invoke the method. This error occurs if the qualifying
type, T, is a subtype of two interfaces, I and J, where both I and J
declare a default method with the same signature and result, and
neither I nor J is a subinterface of the other.

In other words, adding a default method is a binary-compatible change
because it does not introduce errors at link time, even if it
introduces errors at compile time or invocation time. In practice, the
risk of accidental clashes occurring by introducing a default method
are similar to those associated with adding a new method to a
non-final class. In the event of a clash, adding a method to a class
is unlikely to trigger a LinkageError, but an accidental override of
the method in a child can lead to unpredictable method behavior. Both
changes can cause errors at compile time.

The reason you got the IncompatibleClassChangeError is probably because, you didn’t recompile your C class, after adding the default method in B interface.

Also see:

  • Compatibility Guide for JDK 8.

Leave a Comment

tech