Default Methods


Idioms and Techniques

Design Rationale

Advanced Questions

How are conflicting method declarations resolved?

Because inheritance is possible from multiple interfaces, the same default method can be inherited from different paths. Since each inherited default method provides a different implementation, the compiler needs a way of selecting the declaration to use. This is its method:

  • Classes always win. A declaration in the class or a superclass takes priority over any default method declaration.
  • Otherwise, the method with the same signature in the most specific default-providing interface is selected. For example, based on the rules above the following code will print  Hello World from B:
        public interface A {
            default void hello() { System.out.println("Hello World from A"); }
        public interface B extends A {
            default void hello() { System.out.println("Hello World from B"); }
        public class C implements B, A {
            public static void main(String... args) {
                new C().hello();

Conflicts are not always avoidable. If, in the example above, interface B was declared without extending A, then C would inherit default methods with matching signatures from unrelated interfaces. Compiling that code would produce the error messages:

class C inherits unrelated defaults for hello() from types A and B
reference to hello is ambiguous, both method hello() in A and method hello() in B match.

Note that the first error would be reported whether or not there was a call to the inherited default method. The conflict must be resolved by overriding. If desired, one of the inherited methods can be selected using the new syntax X.super.m(...) where X is the superinterface and m the method to select:

    public class C implements B, A {
        public void hello() {

This now prints  Hello World from A. Note that this syntax can only be used to resolve a conflict, not to override either of the two principal rules listed above.