ReviseAlgo Logo

Inheritance

Multiple Inheritance

Dissect interface-based multiple inheritance, default method diamond resolutions, static helpers, and private interface methods.

Interview: Highly tested: Diamond problem resolution rules with default methods (Java 8+), Interface.super call syntax, and static/private interface rules.

Last Updated: June 13, 2026 10 min read

Java supports multiple inheritance of behavior through interfaces. While classes cannot extend multiple classes, a class can implement multiple interfaces. With the introduction of Java 8 default methods, Java resolved the Diamond Problem using clear compiler rules.

Diamond Resolution

If sibling interfaces share a default method signature, the implementing class must override it to resolve ambiguity.

Precedence Rules

Classes take precedence over interfaces. If a parent class and an interface define the same method signature, the class method wins.

Modern Interfaces

Java 8 introduced default/static methods, and Java 9 added private helper methods to support cleaner API design.

Java 8+ Default Method Diamond Problem Resolution

If a class implements two interfaces (e.g., interface A and interface B) that declare identical default methods (e.g., default void print()), the compiler forces resolution:

  • Subclass Must Override: The subclass must override the conflicting method. Failing to do so generates a compilation error.
  • Explicit super Selection: Within the overridden method, you can select which interface's method to run using the syntax InterfaceName.super.methodName().

Modern Interface Methods (Static & Private)

Interfaces have evolved to provide complete behavioral modules:

  • Static Interface Methods (Java 8+): Behave like utility methods. They belong to the interface class itself, cannot be overridden, and are called using InterfaceName.staticMethodName().
  • Private Interface Methods (Java 9+): Allow sharing common code between default methods within the same interface without exposing them publicly to implementing classes.

Common Pitfalls

  • Assuming default methods are polymorphic state carriers: Interfaces cannot hold instance fields, so default methods can only run behavior based on parameters or interface method calls.
  • Calling static interface methods on instances: Attempting to call an interface static method using an implementing class reference (e.g., classRef.staticMethod()), which is illegal in Java.

Best Practices

  • Use Default Methods for API Evolution: Use default methods primarily to add new capability methods to interfaces without breaking existing implementations.
  • Keep Interface Methods Focused: Interfaces should model capabilities. Keep default method bodies small and delegate complex operations to helper classes.

Interview-Relevant Information

Q1: What are the three resolution rules for default method conflicts?
Answer: 1. Classes win: A method in a superclass takes precedence over any interface default method.
2. Subinterface wins: If an interface extends another interface, the default method in the subinterface overrides the superinterface.
3. Explicit override: If two unrelated interfaces declare the same default method, the implementing class must explicitly override and resolve the conflict.

Q2: Can we override a default method in an implementing class?
Answer: Yes. Implementing classes can override default methods to provide specialized behavior, just like overriding ordinary class methods.

Quick Checklist

Can you explain the three default method precedence rules, resolve duplicate default method conflicts using super syntax, and list interface method features introduced in Java 8 and 9? If yes, you understand interface-based multiple inheritance.

Use Cases

Designing plugin behavior contracts (e.g., a class implementing Runnable, Serializable, and Comparable).

Evolving library interfaces safely by adding default operations without breaking client applications.

Common Mistakes

Forgetting to resolve default method conflicts between sibling interfaces, which leads to compile-time failures.

Attempting to declare instance variables inside interfaces to hold state.