HuntExams Academy logo
JavaAdvanced#oop#interface

What is the diamond problem and how does Java avoid it with interfaces?

Answer

The diamond problem occurs when a class inherits conflicting implementations of the same method from multiple parents. Java avoids ambiguity with multiple inheritance of classes entirely, but for interface default methods, the compiler forces the implementing class to explicitly override the conflicting method.

Example

interface A { default void greet() { System.out.println("A"); } }
interface B { default void greet() { System.out.println("B"); } }
class C implements A, B {
  public void greet() { A.super.greet(); } // must resolve explicitly
}

Detailed explanation

The diamond problem is an ambiguity caused by inheriting competing implementations of the same method through multiple inheritance paths. In the classic diamond shape, two parent types share an ancestor, and a child inherits from both parents. If the parents provide different implementations, which one should the child use? The practical issue is conflicting inherited behaviour, not merely the presence of multiple interfaces. Interviewers expect you to distinguish multiple inheritance of classes from multiple inheritance of interface contracts and default implementations.

Java prevents multiple inheritance of classes: a class can extend only one class, so it cannot inherit competing implementations from two direct superclasses. However, a class can implement multiple interfaces. Before Java 8, interfaces did not provide default method bodies, so matching abstract declarations with compatible return types could be satisfied by one implementation. Java 8 introduced default methods, allowing interfaces to supply inherited behaviour. This created possible implementation conflicts, which Java handles through compile-time resolution rules rather than arbitrary selection.

Three rules are central. First, a concrete instance method inherited from a superclass takes precedence over an interface default method, provided it satisfies the interface contract. Second, among interfaces, a more specific interface's override takes precedence over its ancestor's default. Third, if unrelated interfaces provide competing defaults and no class method resolves the conflict, the implementing class must explicitly override the method. For example, if A and B each declare default void greet(), class C implements A, B must declare public void greet(). Without that override, compilation fails.

Inside C's override, A.super.greet() explicitly calls A's default implementation in this example, where A is a direct superinterface. C could instead call B.super.greet(), invoke both, or provide entirely new behaviour. This is compile-time disambiguation; Java does not choose according to interface declaration order. Also, a diamond is not automatically an error: if two interfaces simply inherit the same unchanged default from one common ancestor, there is no competing implementation to resolve.

Key points to remember

  • Java allows one direct superclass but multiple implemented interfaces.
  • Interface default methods, introduced in Java 8, can create implementation conflicts.
  • An inherited concrete superclass method takes precedence over an interface default.
  • A more specific interface override takes precedence over an ancestor's default.
  • Unrelated competing defaults require an explicit public override; InterfaceName.super.method() can select an eligible default.

Common mistakes candidates make

  • Saying interfaces completely prevent the diamond problem without mentioning default-method conflicts.
  • Assuming Java selects the first interface listed in the implements clause.
  • Treating every diamond-shaped interface hierarchy as ambiguous, even when both paths inherit the same unchanged default.

Likely follow-up questions

What happens if C does not override greet() in the example?

Compilation fails because C would inherit competing defaults from unrelated interfaces A and B. Java requires the conflict to be resolved explicitly rather than choosing an implementation at runtime.

Can the overriding method call both default implementations?

Yes: in this example, its body can contain A.super.greet(); followed by B.super.greet();. These qualified calls explicitly invoke the respective defaults, and C controls their order.

What if B extends A and overrides A's default method?

B's default is more specific and takes precedence over A's default. A class implementing B inherits that implementation unless a class method takes precedence or the class provides its own override.

Interview tip: Define the ambiguity, state Java's three resolution rules, and demonstrate the explicit override using A.super.greet().

Related Interview Questions

1
JavaIntermediate#serialization#keywords

What is the purpose of the transient keyword outside of serialization context — does it affect anything else?

Open
2
JavaIntermediate#interface#java8

What is the difference between an interface's default method and a static method?

Open
3
JavaAdvanced#streams#exceptions

What is the difference between checked exception wrapping in streams' lambdas — why can't you throw checked exceptions inside a lambda directly used in a stream?

Open