The simple answer is that it allows you to evolve an existing interface without breaking existing implementations.
For example, you have Swim
interface that you published 20 years ago.
public interface Swim {
void backStroke();
}
We did a great job, our interface is very popular, there are many implementation on that around the world and you don't have control over their source code.
public class FooSwimmer implements Swim {
public void backStroke() {
System.out.println("Do backstroke");
}
}
After 20 years, you've decided to add new functionality to the interface, but it looks like our interface is frozen because it will break existing implementations.
Luckily Java 8 introduces brand new feature called Default method.
We can now add new method to the Swim
interface.
public interface Swim {
void backStroke();
default void sideStroke() {
System.out.println("Default sidestroke implementation. Can be overridden");
}
}
Now all existing implementations of our interface can still work. But most importantly they can implement the newly added method in their own time.
One of the biggest reasons for this change, and one of its biggest uses, is in the Java Collections framework. Oracle could not add a foreach
method to the existing Iterable interface without breaking all existing code which implemented Iterable. By adding default methods, existing Iterable implementation will inherit the default implementation.