2 min read

Static and Default Methods in Java Interfaces

Default and static methods allow you to have utility methods or default implementations.
Static and Default Methods in Java Interfaces

Static Methods

Java 8 introduced the ability to add static methods to interfaces. Static methods on interfaces work the same way as static methods on classes. Static methods on interfaces are implicitly public, so providing the public modifier is redundant. The following example shows a static method in an interface.

public interface Example {

    static void print(final String value) {
        System.out.println(value);
    }
}

Java 9 introduced the ability to use the private modifier on static interfaces. This allows you to break out and reuse code that is used in static methods.

public interface User {

    String firstName();
    
    String lastName();
    
    static int firstNameLength() {
        return calcLength(firstName());
    }
    
    static int lastNameLength() {
        return calcLength(lastName());
    }
    
    private static int calcLength(final String length) {
        // ...
    }
}

Default Methods

Java 8 introduced the ability to have default methods in an interface using the default keyword. Default methods allow you to provide a default implementation of a method. This is a similar concept to a method in an abstract class. Default methods can be overridden and are useful when introducing new methods to an interface.

Default methods are really useful to not break existing code. Depending on your project, if the interface is used by other projects, it shouldn't change once it is released, or you will break all classes that implement that interface. When you run into this situation, you can do one of three things. The first is to break all classes that implement that interface. The second is to provide a new interface.

// Original
public interface MyInterface {

    void method1();
}

// New interface
public interface MyInterfaceVersion2 implements MyInterface {

    void method2();
}

This allows you to extend the new interface without breaking existing code.

The third is to use a default method.

public interface MyInterface {

    void method1();
    
    default void method2() {
        // ...
    }
}

A default method allows the interface to change without breaking all of the classes that implement that interface.

Default Method Conflicts

If you have two interfaces, both with a default method with the same method signature, and a class implements both of these interfaces, it will result in a compiler error.

public interface MyInterface1 {
    default void greet() {
        System.out.println("Hello 1");
    }
}

public interface MyInterface2 {
    default void greet() {
        System.out.println("Hello 2");
    }
}

// Compiler error:
//   MyClass inherits unrelated defaults for greet() from
//   types MyInterface1 and MyInterface2
public class MyClass implements MyInterface1, MyInterface2 {
}

To fix this, you have to provide an implementation of the method that has the conflict.

public class MyClass implements MyInterface1, MyInterface2 {
    
    @Override
    public void greet() {
        System.out.println("Hello MyClass");
    }
}

If you want to use the default method in one of the interfaces, you can do this with the following:

public class MyClass implements MyInterface1, MyInterface2 {
    
    @Override
    public void greet() {
        MyInterface1.super.greet();
    }
}

This uses the greet() method in MyInterface1.

Private Methods

Java 9 introduced the ability to have not just private static methods but private methods in interfaces. This allows the same power as a static method but instead is used with default methods.

public interface User {

    String firstName();
    
    String lastName();
    
    default int firstNameLength() {
        return calcLength(firstName());
    }
    
    default int lastNameLength() {
        return calcLength(lastName());
    }
    
    private int calcLength(final String length) {
        // ...
    }
}

Conclusion

Interface support having static methods similar to classes that have static methods. Interfaces also support providing a default implementation of a method. This allows you to not implement a method when you don't need to or prevents breaking all classes that implement that interface.