93. Interface Default Method Diamond Problem
When a class inherits two interfaces with conflicting default methods, it must override to resolve the ambiguity โ the compiler rejects the ambiguity; a superclass method always wins over an interface default.
Explanation
Java's resolution rules for default method conflicts:
Rule 1 โ Class always wins: if a class (or its superclass) provides a concrete method with the same signature, it takes precedence over any interface default. This ensures backwards compatibility โ pre-Java-8 classes are never affected by new default methods added to interfaces they implement.
Rule 2 โ More specific interface wins: if one interface extends the other, the more derived interface's default wins.
Rule 3 โ Must override: if Rules 1 and 2 don't resolve the conflict (two unrelated interfaces both provide a default with the same signature), the implementing class must explicitly override the method and choose which interface's implementation to invoke via InterfaceName.super.method().
Example
public class DefaultMethodDiamond {
interface A {
default String hello() { return "Hello from A"; }
}
interface B {
default String hello() { return "Hello from B"; }
}
interface C extends A {
@Override
default String hello() { return "Hello from C (extends A)"; }
}
// Rule 1: class method wins over any default
static class SuperClass {
public String hello() { return "Hello from SuperClass"; }
}
// Rule 2: C (more specific) wins over A
static class ImplAC implements A, C {
// No override needed โ C wins (C extends A)
}
// Rule 3: A and B conflict โ must override
static class ImplAB implements A, B {
@Override
public String hello() {
// Choose explicitly, or provide own implementation
return A.super.hello() + " + " + B.super.hello();
}
}
// Rule 1: SuperClass.hello() wins over A.hello() and B.hello()
static class ImplExtends extends SuperClass implements A, B {
// No override needed โ SuperClass.hello() wins
}
public static void main(String[] args) {
System.out.println(new ImplAC().hello()); // Hello from C (extends A)
System.out.println(new ImplAB().hello()); // Hello from A + Hello from B
System.out.println(new ImplExtends().hello()); // Hello from SuperClass
// What happens without resolution: COMPILE ERROR
// class Bad implements A, B {} // error: inherits unrelated defaults
}
}Sources
- https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html โ Default methods tutorial
- https://docs.oracle.com/javase/specs/jls/se21/html/jls-9.html#jls-9.4.1 โ JLS: default method resolution