BinaryCompatibleDefaultMethods
From APIDesign
DefaultMethods are useful when one desperately needs to add a method into an existing interface. However, they decrease clarity of a ProviderAPI (no, you can't disagree!). As such, don't overuse. Morever it has been recently demonstrated that adding DefaultMethods can even compromise BinaryCompatibility. Recently Emilian Bold asked me to participate in a tweeting about binary incompatibility caused by adding CharSequence.isEmpty in JDK15. An interesting case. Following code compiles on JDK8 to JDK14:
interface ArrayLike { int length(); default boolean isEmpty() { return length() == 0; } } final class CharArrayLike implements CharSequence, ArrayLike { private final char[] chars; CharArrayLike(char[] chars) { this.chars = chars; } @Override public int length() { return chars.length; } @Override public char charAt(int index) { return chars[index]; } @Override public CharSequence subSequence(int start, int end) { return new String(chars, start, end); } }
While the code compiles find with JDK14 and older, it no longer compiles on JDK15. It results in:
$ /jdk-14/bin/javac ArrayLike.java $ /jdk-15/bin/javac ArrayLike.java ArrayLike.java:9: error: types CharSequence and ArrayLike are incompatible; final class CharArrayLike implements CharSequence, ArrayLike { ^ class CharArrayLike inherits unrelated defaults for isEmpty() from types CharSequence and ArrayLike 1 error
Why? Since JDK15 there is CharSequence.isEmpty() default method. As such, when javac processes the CharArrayLike class it doesn't know whether to select the ArrayLike.isEmpty() or the newly added method.