default, static & private interface methods
Java 8+ added method bodies to interfaces — how each kind works and when to use it.
default methods — API evolution without breaking changes
Java 8 introduced default methods: interface methods with a full body, marked default. A class that implements the interface inherits the default implementation and may override it:
public interface Logger {
void log(String msg); // abstract — must implement
default void logInfo(String msg) { // default — inherited or overridable
log("[INFO] " + msg);
}
}
public class ConsoleLogger implements Logger {
@Override
public void log(String msg) { System.out.println(msg); }
// logInfo is inherited — no need to implement it
}
Why they exist: before Java 8, adding a method to a published interface broke every existing implementation. Default methods let library authors add new methods without forcing every user to update.
static interface methods
Declared with static, called via the interface name — not inherited by implementing classes:
public interface MathOp {
static int clamp(int v, int lo, int hi) {
return Math.max(lo, Math.min(hi, v));
}
}
int x = MathOp.clamp(150, 0, 100); // 100
private interface methods (Java 9+)
Private methods (with or without static) allow code to be shared between default methods without exposing it as part of the interface's API:
public interface Validator {
default boolean isValid(String s) { return !isEmpty(s); }
default boolean isBlank(String s) { return isEmpty(s); }
private boolean isEmpty(String s) { return s == null || s.isEmpty(); }
}