SyntaxStudy
Sign Up
Java Default and Static Interface Methods
Java Beginner 1 min read

Default and Static Interface Methods

Java 8 added default methods to interfaces, allowing an interface to provide a concrete implementation. Default methods solve the backward-compatibility problem: you can add new methods to an existing interface without breaking all existing implementations. A class can override a default method to provide its own behaviour, or inherit the default implementation. If a class implements two interfaces that both declare a default method with the same signature, the compiler forces the class to override the method and resolve the conflict explicitly. It can call a specific interface default via InterfaceName.super.method(). This prevents the diamond problem in a controlled way. Static methods in interfaces (Java 8+) belong to the interface type itself, like static methods in classes. They cannot be overridden or inherited by implementing classes. They are commonly used for factory methods or utility functions that are logically related to the interface. Java 9 also added private methods to interfaces, which allow shared helper logic between default methods without exposing it as part of the public API.
Example
import java.util.Comparator;
import java.util.List;

interface Validator<T> {

    // Abstract method
    boolean isValid(T value);

    // Default method — provides a convenience inverse
    default boolean isInvalid(T value) {
        return !isValid(value);
    }

    // Default method — and-combination of validators
    default Validator<T> and(Validator<T> other) {
        return value -> this.isValid(value) && other.isValid(value);
    }

    // Static factory method
    static <T> Validator<T> nonNull() {
        return value -> value != null;
    }
}

class RangeValidator implements Validator<Integer> {
    private final int min, max;
    RangeValidator(int min, int max) { this.min = min; this.max = max; }

    @Override
    public boolean isValid(Integer value) {
        return value != null && value >= min && value <= max;
    }
}

interface Greetable {
    default String greet(String name) { return "Hello, " + name; }
}

interface Farewell {
    default String greet(String name) { return "Goodbye, " + name; } // same signature!
}

class ConflictResolved implements Greetable, Farewell {
    @Override
    public String greet(String name) {
        // Must override to resolve the conflict
        return Greetable.super.greet(name) + " / " + Farewell.super.greet(name);
    }
}

public class DefaultStaticMethods {
    public static void main(String[] args) {
        Validator<Integer> range   = new RangeValidator(1, 100);
        Validator<Integer> nonNull = Validator.nonNull();
        Validator<Integer> both    = nonNull.and(range);

        List.of(null, -5, 0, 50, 100, 101).forEach(v ->
            System.out.printf("%-5s -> valid=%b, invalid=%b%n",
                v, both.isValid(v), both.isInvalid(v))
        );

        ConflictResolved cr = new ConflictResolved();
        System.out.println(cr.greet("Alice"));
    }
}