← Back to Home

Default Methods

Default methods were introduced in Java 8 to allow interfaces to have method implementations. They enable interface evolution without breaking existing implementations and are a key enabler for functional programming features (lambdas, streams). This is a frequent interview topic, especially around diamond problem resolution.

What Is a Default Method?

A default method is a method in an interface that has a method body and is declared using the default keyword.

interface Vehicle {
    default void start() {
        System.out.println("Vehicle started");
    }
}
          
  • ✔ Method has implementation
  • ✔ Classes implementing the interface inherit it automatically

Why Default Methods Were Introduced

Before Java 8:

  • Interfaces could have only abstract methods
  • Adding a new method broke all implementing classes

With Java 8:

  • Default methods allow backward compatibility
  • Existing classes need no change

Syntax Rules

interface InterfaceName {
    default returnType methodName() {
        // implementation
    }
}
          
  • ✔ Must have a body
  • ✔ Cannot be abstract
  • ✔ Implicitly public

Using Default Methods

Interface

interface Printer {
    default void print() {
        System.out.println("Printing...");
    }
}
          

Implementing Class

class LaserPrinter implements Printer {
    // no need to override print()
}
          

✔ print() available automatically

Overriding Default Methods

Implementing classes can override default methods.

class InkjetPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("Inkjet printing...");
    }
}
          

✔ Class version takes precedence

Default Methods vs Abstract Methods

Aspect Default Method Abstract Method
Has body ✔ Yes ❌ No
Mandatory override ❌ No ✔ Yes
Introduced Java 8 Java 1.0
Backward compatible ✔ Yes ❌ No

Default Methods vs Static Methods in Interface

Aspect Default Method Static Method
Called via Object Interface name
Inherited ✔ Yes ❌ No
Overridable ✔ Yes ❌ No
interface Utils {
    default void show() {}
    static void help() {}
}
          

Diamond Problem & Default Methods (Very Important)

Scenario: Two Interfaces, Same Default Method

interface A {
    default void show() {
        System.out.println("A");
    }
}

interface B {
    default void show() {
        System.out.println("B");
    }
}

class Test implements A, B {
    // ❌ Compilation error unless overridden
}
          

Resolving the Conflict

class Test implements A, B {
    @Override
    public void show() {
        A.super.show(); // or B.super.show()
    }
}
          
  • ✔ Class must override
  • ✔ Explicitly choose which interface method to call

Interface vs Class Priority Rule (Interview Rule)

  1. Class methods win over interface default methods
  2. More specific interface wins
  3. If ambiguity → class must override
class Parent {
    public void show() {}
}

interface Child {
    default void show() {}
}
          

✔ Parent.show() is used

Default Methods & Functional Interfaces

  • ✔ Functional interfaces can have default methods
  • ✔ Only one abstract method allowed
@FunctionalInterface
interface Task {
    void execute();

    default void log() {
        System.out.println("Logging...");
    }
}
          

✔ Still a functional interface

Real-World Usage Examples

  • Collection → forEach()
  • List → sort()
  • Iterator → forEachRemaining()

These were added without breaking old code.

Common Beginner Mistakes

  • Forgetting default keyword
  • Assuming default methods are mandatory
  • Confusing static and default methods
  • Not resolving diamond conflict
  • Overusing default methods

Best Practices

  • Use default methods sparingly
  • Avoid adding business logic to interfaces
  • Prefer abstract classes for stateful behavior
  • Use default methods for common behavior
  • Always resolve ambiguity explicitly

Interview-Ready Answers

Short Answer

Default methods allow interfaces to have method implementations.

Detailed Answer

In Java 8, default methods were introduced to allow interfaces to provide method implementations using the default keyword. They enable backward compatibility when interfaces evolve and support functional programming features, while still allowing implementing classes to override the default behavior.

Key Takeaway

Default methods make interfaces evolvable. They balance flexibility and compatibility, but should be used carefully to avoid design complexity.

Default Methods Examples (Quick Reference)

1. Basic Default Method in Interface

interface Vehicle {
    default void start() {
        System.out.println("Vehicle starting");
    }
}

class Car implements Vehicle {
}

class Demo {
    public static void main(String[] args) {
        new Car().start();
    }
}
          

Output

Vehicle starting

2. Class Inheriting Default Method Automatically

interface Printer {
    default void print() {
        System.out.println("Printing...");
    }
}

class HPPrinter implements Printer {
}
          

Explanation

  • Implementing class need not override
  • Default method is inherited

3. Overriding Default Method in Class

interface Printer {
    default void print() {
        System.out.println("Default print");
    }
}

class LaserPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("Laser print");
    }
}
          

4. Calling Interface Default Method from Override

interface Printer {
    default void print() {
        System.out.println("Default print");
    }
}

class InkPrinter implements Printer {
    public void print() {
        Printer.super.print();
        System.out.println("Ink print");
    }
}
          

Output

Default print
Ink print
          

5. Multiple Interfaces with Same Default Method (Conflict)

interface A {
    default void show() {
        System.out.println("A");
    }
}

interface B {
    default void show() {
        System.out.println("B");
    }
}

class Demo implements A, B {
    public void show() {
        System.out.println("Resolved");
    }
}
          

Rule

Must override to resolve ambiguity.

6. Resolving Conflict Using InterfaceName.super

class Demo implements A, B {
    public void show() {
        A.super.show();
        B.super.show();
    }
}
          

7. Default Method vs Abstract Method

interface A {
    default void run() {
        System.out.println("Default run");
    }
}

interface B {
    void run();
}

class Demo implements A, B {
    public void run() {
        System.out.println("Implemented run");
    }
}
          

Rule

  • Abstract method wins
  • Must implement

8. Default Method vs Class Method (Class Wins)

interface A {
    default void test() {
        System.out.println("Interface");
    }
}

class Base {
    public void test() {
        System.out.println("Class");
    }
}

class Demo extends Base implements A {
}
          

Output

Class

9. Default Method Cannot Override Object Methods

interface A {
    // default String toString() { } ❌ not allowed
}
          

Reason

Object methods cannot be default methods.

10. Default Method with Parameters

interface Calculator {
    default int add(int a, int b) {
        return a + b;
    }
}

class Demo {
    public static void main(String[] args) {
        Calculator c = new Calculator() {};
        System.out.println(c.add(5, 7));
    }
}
          

11. Default Method Using Private Helper Method (Java 9+)

interface Logger {
    default void log() {
        helper();
    }

    private void helper() {
        System.out.println("Logging...");
    }
}
          

12. Default Method + Lambda (Not Used Together)

@FunctionalInterface
interface Task {
    void run();

    default void info() {
        System.out.println("Task info");
    }
}
          

Note

Still functional (only one abstract method).

13. Default Method in Functional Interface

@FunctionalInterface
interface Printer {
    void print();

    default void status() {
        System.out.println("Ready");
    }
}
          

14. Using Default Method via Interface Reference

Printer p = () -> System.out.println("Printing");
p.status();
p.print();
          

15. Multiple Default Methods (No Conflict)

interface A {
    default void a() {}
}

interface B {
    default void b() {}
}

class Demo implements A, B {
}
          

16. Default Method Evolution Use Case (Java 8 Reason)

interface ListV1 {
    void add();
}

// Later version
interface ListV2 {
    default void size() {
        System.out.println("Size");
    }
}
          

Explanation

Prevents breaking existing implementations.

17. Default Method Cannot Access Instance Fields

interface A {
    default void test() {
        // System.out.println(x); ❌ no instance fields
    }
}
          

18. Default Method Access Modifiers

interface A {
    default void a() {}     // public by default
    // protected/private ❌ not allowed (Java 8)
}
          

19. Real Interview Trap

interface A {
    default void run() {}
}

class Demo implements A {
    // No override needed
}
          

Interview Question

Is override mandatory? → ❌ No

20. Default Method vs Static Method

interface A {
    default void d() {
        System.out.println("Default");
    }

    static void s() {
        System.out.println("Static");
    }
}

A a = new A() {};
a.d();
// a.s(); ❌ not allowed
A.s();   // ✅
          

21. Default Method with Interface Inheritance

interface A {
    default void show() {
        System.out.println("A");
    }
}

interface B extends A {
}

class Demo implements B {
}
          

22. Overriding Default Method as Abstract

interface A {
    default void show() {}
}

interface B extends A {
    void show(); // makes it abstract again
}
          

23. Default Method Cannot Be final

interface A {
    // default final void test() {} ❌
}
          

24. Default Method Real-World Usage

// Java Collections (forEach, removeIf)
// Comparator.thenComparing()
// Iterable.forEach()
          

25. Interview Summary – Default Methods

default method = concrete method in interface

Key Points

  • Introduced in Java 8
  • Enables interface evolution
  • Class method > interface default
  • Conflict must be resolved explicitly
  • Supports code reuse without breaking changes