Default methods and why they exist
Default methods were not a convenience - they were the only way to add stream() to Collection.
Open this lesson in the learning hubKey points
- Before 8, adding a method to a published interface broke every implementation on the planet.
- That is why
Collection.stream()could not exist: it would have broken all third-party collections. - A default method ships a body, so existing implementors inherit it and keep compiling.
- The cost: inherit the same default from two interfaces and you must override to resolve it.
- Use them to evolve an interface, not as a place to hide real logic - that belongs in a class.
Example
import java.util.*;
public class Main {
interface Logger {
void log(String msg); // implementors must write this
default void warn(String msg) { // added later, breaks nobody
log("WARN " + msg);
}
}
static class ConsoleLogger implements Logger {
@Override public void log(String msg) { System.out.println(msg); }
}
static class LoudLogger implements Logger {
@Override public void log(String msg) { System.out.println(msg); }
@Override public void warn(String msg) { log("!!!! " + msg.toUpperCase()); }
}
public static void main(String[] args) {
new ConsoleLogger().warn("inherited the default");
new LoudLogger().warn("overrode the default");
// The real motivation: Collection gained stream() without breaking anyone
System.out.println(List.of(1, 2, 3).stream().mapToInt(Integer::intValue).sum());
}
}
Default methods exist so a published interface can grow without breaking its implementors.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Java 8 Course course, and every lesson in it is listed on the Java 8 Course contents page.