When two unrelated interfaces provide default methods with the same signature, an implementing class must resolve the conflict explicitly.
Java interface defaults: resolve a two-parent method conflict
Operational contract
The concrete formatter chooses the audit label and receipt label in a fixed order. It calls the two parent defaults with qualified InterfaceName.super syntax, then returns a new label. This decision belongs in the class that combines both contracts. A superclass concrete method can take precedence over interface defaults, so changing a class hierarchy may change dispatch even when interface source remains the same. Default methods add API behavior; they do not replace a review of semantic compatibility between the interfaces.
Failure case
A reporting type implements both a receipt naming interface and an audit naming interface. Each supplies label(). Without an override, compilation fails. The explicit result 'AUDIT-82 / RECEIPT-47' makes the combined naming rule visible to callers and reviewers.
Java code
public class CombinedReceiptLabel {
interface ReceiptLabel { default String label() { return "RECEIPT-47"; } }
interface AuditLabel { default String label() { return "AUDIT-82"; } }
static final class ReportLabel implements ReceiptLabel, AuditLabel {
@Override public String label() {
return AuditLabel.super.label() + " / " + ReceiptLabel.super.label();
}
}
public static String render() {
return new ReportLabel().label();
}
}Performance and ownership cost
Dispatch and concatenation are constant work for these fixed strings; the returned string allocates storage proportional to its length. The main cost is API governance: every conflict resolution should encode a deliberate business rule rather than blindly pick the first parent.
Common Mistakes
- Do not expect Java to select one of two unrelated defaults automatically.
- Do not resolve a conflict with an arbitrary parent when both semantics matter.
- Do not overlook superclass methods when reasoning about inherited behavior.
Connected lessons
- Java interfaces and replaceable behavior
- Java polymorphism: overriding and dispatch
- Java method overloads: compile-time selection and dispatch
- Java compact record constructors: normalize before field assignment
- Java instanceof patterns: keep a narrowed value inside its valid scope
- Java switch expressions: return one value from every state
- Java sealed hierarchies: switch over permitted request kinds
- Java generics and language contracts quiz
- Advanced Java
