Abstraction
Default Methods
Dissect default methods in interfaces, safe API evolution strategies, and diamond conflict resolutions.
Interview: Critical: diamond problem resolution, InterfaceName.super reference syntax, and interface evolution rules.
Default Methods (introduced in Java 8) allow interfaces to declare methods with implementation bodies using the default modifier. They enable safe API evolution without breaking backward compatibility for existing implementing classes.
API Evolution
Allows adding new methods to interfaces with default implementation bodies, preventing compile errors in legacy implementer classes.
Diamond Conflict
If sibling interfaces share a default method signature, the implementing class must explicitly override and resolve the conflict.
Class Rules Win
Class implementation takes absolute priority over interface defaults. A superclass method signature always wins.
Why Default Methods?
Before Java 8, adding a new method to an interface (like forEach in java.lang.Iterable) required every implementing class in existence to be updated with an implementation. To facilitate library evolution (especially lambda integrations in the Collections framework), default methods were introduced to supply fallback implementations.
Default Method Diamond Problem Resolution
If a class implements two interfaces declaring identical default method signatures, a conflict occurs. Java resolves this with three precedence rules:
- Classes Win: A method in a superclass takes precedence over any interface default method.
- Subinterface Wins: If interface
B extends A, the default method inBoverrides the default method inA. - Explicit Override: If the interfaces are sibling types (not inherited), the class must override the method. Within the override, the developer can explicitly invoke an interface method using
InterfaceName.super.methodName().
Common Pitfalls
- Forgetting to resolve duplicate signatures: Implementing conflicting interfaces without writing a resolving override in the subclass, causing compilation failures.
- Treating default methods as state-bearing: Attempting to store or modify object variables directly inside default methods (which is impossible since interfaces cannot hold instance state).
Best Practices
- Use for Optional Methods: Use default methods to provide empty or default bodies for optional interface methods, reducing boilerplate in client classes.
- Keep Evolution Backward-Compatible: Only introduce default implementations that are generic enough to work across all implementing classes.
Interview-Relevant Information
Q1: What happens if a class implements an interface with a default method, and extends a superclass that has a method with the same signature?
Answer: The superclass method implementation is executed. Java's "class wins" rule dictates that class-level implementations always take precedence over interface default methods.
Q2: How do you invoke a default method of a specific parent interface from an implementing class?
Answer: By using the syntax: InterfaceName.super.methodName(); inside the overriding class method.
Quick Checklist
Can you write a default method in an interface, explain the "class wins" precedence rule, and resolve a diamond conflict using the super syntax? If yes, you understand default methods.
Use Cases
Evolving legacy API interfaces safely without breaking client application implementations.
Providing default empty behavior for listener callback interface configurations.
Common Mistakes
Failing to override conflicting default methods in implementing subclasses, leading to compiler failures.
Attempting to override final default methods declared in super-interfaces.