Default Methods and the Diamond
What happens when two interfaces hand you the same default method, and how to pick.
Open this lesson in the learning hubKey points
- Java resolves it in a fixed order: a method in the class body wins over any interface default, always.
- Otherwise the most specific interface wins: if
Formal extends Greeter, the Formal default is used. - If the two interfaces are unrelated, neither is more specific, so the compiler refuses and you must override.
- Inside your override, call the one you want with
Formal.super.hi(). You can call both if that helps. - This is why Java can have multiple inheritance of behaviour without the classic diamond of state.
- If defaults keep colliding, the interfaces are probably doing too much. Split them by capability.
Example
public class Main {
interface Greeter { default String hi() { return "hello"; } }
interface Formal extends Greeter { // more specific than Greeter
@Override default String hi() { return "Good evening"; }
}
interface Casual { default String hi() { return "Yo"; } }
// Formal beats Greeter automatically: the most specific interface wins.
static class Host implements Formal, Greeter { }
// Formal and Casual are unrelated, so the compiler refuses to guess. Pick one.
static class Waiter implements Formal, Casual {
@Override public String hi() {
return Formal.super.hi() + " (chose Formal over " + Casual.super.hi() + ")";
}
}
// A method in the class body always wins over any interface default.
static class Robot implements Formal {
@Override public String hi() { return "BEEP"; }
}
public static void main(String[] args) {
System.out.println(new Host().hi());
System.out.println(new Waiter().hi());
System.out.println(new Robot().hi());
}
}
Class beats interface, specific beats general, and a tie is your decision to make.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the OOP course, and every lesson in it is listed on the OOP contents page.