skip to content

A class implements two interfaces that each provide a default method with the same signature. What happens, and how do you resolve it?

level: seniorimportance: must knowfreq 60%

answer

  1. Class wins > more-specific interface wins > else compile error
  2. Unrelated sibling defaults => you must override
  3. Delegate with Interface.super.method()
  4. Clash is by signature, not body
  5. Java refuses to silently guess

basics

~10 s

If two interfaces give the same default method, the class won't compile until you resolve the clash. You override the method in the class, and you can pick one parent's version with InterfaceName.super.method().

solid answer

~40 s

When a class inherits two default methods with the same signature from unrelated interfaces, Java cannot decide which one wins, so the compiler reports an error and forces you to override the method in the class. Inside that override you may delegate to a specific parent with the syntax InterfaceName.super.method(). Java does have two automatic tie-break rules first: (1) a class (or superclass) concrete method always beats any interface default — class wins; and (2) a more specific sub-interface's default beats a less specific super-interface's default. Only when neither rule resolves the conflict (two sibling interfaces at the same level) must you intervene manually. These rules are Java's deliberately conservative answer to the multiple-inheritance diamond problem: it permits multiple inheritance of behaviour but never silently guesses which conflicting implementation to use.

code

java · 10 lines
java
interface Drawable { default String render() { return "draw"; } }
interface Printable { default String render() { return "print"; } }

class Document implements Drawable, Printable {
    // Without this override the class does NOT compile:
    // "inherits unrelated defaults for render() from Drawable and Printable"
    @Override public String render() {
        return Drawable.super.render() + "/" + Printable.super.render();
    }
}

go deeper

for a junior

Knows that two conflicting default methods cause a compile error and that you override the method to fix it.

for a middle

Can resolve the clash by overriding and delegating with Interface.super.method(), and knows the class-wins rule.

for a senior

States all three resolution rules in order (class wins, more-specific interface wins, else error), uses Interface.super correctly, and knows the clash is by signature and can involve default-vs-abstract.

for a principal

Reasons about diamond resolution as a deliberate language-design choice, anticipates the class-wins shadowing trap during API evolution, and uses re-abstraction to force implementers to choose when adding conflicting defaults to a published hierarchy.

## The diamond problem, restated for Java The classic **diamond problem** of multiple inheritance: type D inherits from B and C, which both inherit from A. If B and C each provide their own version of a method, which does D get? Java forbids multiple inheritance of *classes* partly to avoid this, but default methods reintroduced multiple inheritance of *behaviour* through interfaces — so Java needed precise rules. ## The three resolution rules (in order) When a type could inherit the same method (same name + parameter types) from more than one source, the compiler applies these rules: ### Rule 1 — Classes win over interfaces A concrete method declared in a (super)class always takes precedence over **any** interface default method with the same signature. The default is simply ignored. (This is why adding a default method can never silently change a class that already has its own implementation.) ### Rule 2 — More specific interface wins Between two interface defaults where one interface **extends** the other, the **more specific** (sub-)interface's default wins. If `B extends A` and both define `m()`, an implementer of `B` gets `B`'s `m()`. ### Rule 3 — Otherwise: compile error, you must override If the candidates come from **unrelated** interfaces (neither is a sub-interface of the other) and there's no class implementation, the compiler **cannot choose** and reports: > *"class X inherits unrelated defaults for m() from types A and B"* The class **must** override the method to resolve the ambiguity. ## Resolving manually with `Interface.super` Inside the override you can either write fresh code or explicitly delegate to one (or both) parents using the **`InterfaceName.super.method()`** syntax: ```java interface A { default String hi() { return "A"; } } interface B { default String hi() { return "B"; } } class C implements A, B { @Override public String hi() { return A.super.hi() + B.super.hi(); // explicitly pick / combine } } ``` Note `A.super.hi()` — *not* `super.hi()` and *not* `A.this.hi()`. You may only target a **direct** super-interface this way. ## Important nuances - The clash is about the **signature**, not the body. Even if both defaults have identical bodies, the compiler still errors — it does not compare implementations. - A clash also arises between a **default method and an abstract method** of the same signature from another interface: the implementer must provide an implementation (the abstract one isn't satisfied by an unrelated default automatically unless one interface extends the other). - Re-abstracting: an interface can override an inherited default with an **abstract** redeclaration (`String hi();`) to force implementers to choose. - Rule 1 (class-wins) can be a *trap*: a default method you intended to be used may be silently shadowed by an inherited concrete superclass method. ## Why Java does it this way The design is intentionally **conservative**: Java permits multiple inheritance of *behaviour* but refuses to silently resolve a genuine conflict, forcing the developer to make the choice explicit. This keeps behaviour predictable and prevents the subtle bugs that plague languages with implicit diamond resolution.

  • If a superclass has a concrete method and an interface has a default with the same signature, which is used?
    The superclass's concrete method wins (Rule 1: class beats interface). The interface default is ignored unless the class explicitly overrides and delegates to it.
  • Does the conflict still occur if both default methods have identical bodies?
    Yes. The compiler resolves clashes by signature, not by comparing implementations, so two same-signature defaults from unrelated interfaces still force a manual override.
  • What's the syntax to call a specific parent interface's default from the override?
    InterfaceName.super.method(...). For example A.super.hi(). It must reference a direct super-interface.

saying these in an interview costs you the question

  • Saying Java just picks one default automatically (e.g. the first listed) — it errors for unrelated siblings.
  • Using super.method() instead of Interface.super.method() to disambiguate.
  • Forgetting Rule 1: a concrete superclass method silently beats an interface default.
  • Claiming identical default bodies avoid the conflict — resolution is by signature only.
  • Thinking you can target a non-direct (grand-)super-interface with X.super.

context