Interfaceshard5-8 years

A `Plugin` interface adds `default boolean healthy() { return true; }`. A month later, one plugin author reports their health check is being ignored — the platform always treats their plugin as healthy regardless of what their code does. Their class extends a shared `BasePlugin`, which happens to already declare a public `boolean healthy()` method, unrelated to the interface, returning whether the plugin's background thread is alive. No compiler ever mentioned a conflict. Why not, and what actually happens at the call site?

The diamond rule's resolution order (JLS §9.4.1) puts a class method ahead of any interface default, unconditionally — a superclass method wins over an interface's default method even when that superclass method was written years earlier, for a completely different purpose, and has never heard of the interface it happens to also satisfy. BasePlugin.healthy() was never meant to answer "did this plugin's own health check pass"; it answers "is the background thread alive", and because both methods share the exact name and signature, the class-wins rule quietly makes BasePlugin's pre-existing method serve as the interface's healthy() for every plugin extending it — no override needed, no conflict flagged, because from the compiler's point of view there was never a conflict to flag: a class method simply always outranks an interface default, and that's a rule, not a heuristic that checks whether the two methods mean the same thing.

The lesson behind it →
More on Interfaces