🔌 Interfaces & Abstraction · Intermediate

Default methods in Java

Interface methods with a body; enable API evolution.

🧩 The mysteryHundreds of teams implement your Plugin interface. You need to add one new method. Add it the normal way and you break every single one of them. Now what?

The upgrade problem

Adding a new abstract method to a published interface breaks every class that implements it: none of them has the new method, so none of them compiles. Turning the interface into an abstract class breaks them too. Java needed a third option.

interface Plugin {
    String name();
    String version();   // breaks everyone!
}

default = a method with a body

Since Java 8, an interface method marked **default has a body. Implementing classes inherit it for free**. A default may call the interface's abstract methods — at runtime they dispatch to the real class's version.

interface Greeter {
    String name();
    default String greet() {
        return "Hi " + name();
    }
}
🔮 Predict it

Inherited for free

Bot implements the Greeter from the previous screen but writes only name(). What prints?

class Bot implements Greeter {
    public String name() { return "R2"; }
}
void main() {
    System.out.println(new Bot().greet());
}
  1. Hi R2
  2. Hi null
  3. Compile error: Bot must implement greet()
Show the answer

Bot inherits greet(). Inside it, name() runs Bot's implementation, giving Hi R2. No compile error: defaults already have a body.

Keep it or replace it

A class may override a default like any other method. Calls dispatch on the real object, so Circle's version runs even through a Shape variable: this prints circle.

interface Shape {
    default String label() { return "shape"; }
}
class Circle implements Shape {
    public String label() { return "circle"; }
}
Shape s = new Circle();
s.label();   // "circle"
⚠️ The trap

No fields to play with

A default method can't read or update instance fields of the interface — interfaces have none (any field is a static final constant). Defaults can only work through other methods, such as abstract getters that the implementing class provides.

💼 In the real world

How Java 8 upgraded the world

Java 8 added forEach to Iterable, and stream() and removeIf to Collection, as default methods. Every collection class ever written — including third-party ones — got them overnight without a single line changed. Library authors use the same trick to grow APIs safely.

Key takeaways

  1. default String greet() { ... } has a body inside the interface
  2. Implementers inherit it and can override it
  3. Defaults may call the interface's abstract methods
  4. Defaults can't use instance fields — interfaces have none

💡 A rental car arrives with standard seat settings: you can keep them or adjust them.

🤯 Did you know?

Map.getOrDefault is a default method on the Map interface — and HashMap overrides it with its own faster version. Defaults are a safe baseline, not a cage.

Practice questions

What does this print?

interface Greeter {
    String name();
    default String greet() { return "Hi " + name(); }
}
class Bot implements Greeter {
    public String name() { return "Bot"; }
}
void main() {
    System.out.println(new Bot().greet());
}
  1. Hi Bot
  2. Hi null
  3. Compile error: Bot must implement greet()
  4. Hi Greeter
Check your answer

Hi Bot. Bot inherits greet() from the interface. Inside it, name() dispatches to Bot's implementation, producing "Hi Bot".

What does this print?

interface Shape {
    default String label() { return "shape"; }
}
class Circle implements Shape {
    public String label() { return "circle"; }
}
void main() {
    Shape s = new Circle();
    System.out.println(s.label());
}
  1. circle
  2. shape
  3. shape circle
  4. Compile error
Check your answer

circle. Circle overrides the default. Calls are dispatched on the real object, so Circle's version runs even through a Shape variable.

Next: a class implements two interfaces, and both have a default hi(). Which one wins? (Trick question: neither.)