OOP

22. Interfaces with Default and Static Methods

Since Java 8, interfaces can have default methods (inherited implementations) and static methods; Java 9 added private methods โ€” enabling rich mixin-style abstractions and backwards-compatible API evolution.

Java 8+ (default/static methods); Java 21 (core language)

Explanation

default methods provide a method body inside an interface. Implementing classes inherit the default unless they override it. This allows API evolution: you can add a default method to an existing interface without breaking all existing implementors (they get the default for free).

static interface methods belong to the interface itself (not instances) and cannot be inherited or overridden. They're useful for factory methods and utilities tied to the interface type (List.of(), Comparator.comparing()).

Diamond problem with defaults: if a class implements A, B and both A and B declare default void foo(), the compiler reports an error and requires the class to explicitly override foo(). If a class inherits from both a superclass and an interface that both define foo(), the superclass method always wins (class wins over interface default).

Example

import java.util.List;
import java.util.Comparator;

public class InterfaceDefaultMethods {
    interface Greeter {
        String greet(String name); // abstract

        default String greetLoudly(String name) { // default
            return greet(name).toUpperCase();
        }

        static Greeter formal() { // static factory
            return name -> "Good day, " + name + ".";
        }
    }

    interface Farewell {
        default String farewell(String name) { return "Goodbye, " + name; }
    }

    // Diamond problem: both have farewell โ€” must override
    interface Greeter2 extends Greeter, Farewell {
        // Must override to resolve ambiguity if two defaults conflict
    }

    public static void main(String[] args) {
        Greeter casual = name -> "Hey, " + name + "!";
        System.out.println(casual.greet("Alice"));        // Hey, Alice!
        System.out.println(casual.greetLoudly("Alice")); // HEY, ALICE!

        Greeter formal = Greeter.formal(); // static method
        System.out.println(formal.greet("Bob")); // Good day, Bob.

        // Comparator.comparing โ€” chained static + default methods
        List<String> names = List.of("Charlie", "Alice", "Bob");
        names.stream()
             .sorted(Comparator.comparing(String::length)
                               .thenComparing(Comparator.naturalOrder()))
             .forEach(System.out::println);
    }
}

Sources