JAVA

Default Methods in Java

neal89 2025. 4. 4. 13:37

🔍 Why Were Default Methods Introduced?

Before Java 8, adding a new method to an interface would break all existing classes that implemented the interface but didn’t provide the new method’s implementation. This led to widespread compile-time errors and forced developers to modify all implementing classes, which was especially painful when:

  • The interface was widely used
  • The interface was implemented in external libraries

To solve this, Java 8 introduced default methods, which allow an interface to provide a default implementation for a method. This means:

➤ New methods can be added without breaking existing implementations.
➤ Classes can still override the method if needed.


💡 Example 1 – Interface and Implementation Classes

Assume there’s a Notifier interface used to send notifications, and it has three implementations: EmailNotifier, SMSNotifier, and AppPushNotifier. Each one implements the notify() method.

public interface Notifier {
    void notify(String message);
}
public class EmailNotifier implements Notifier {
    @Override
    public void notify(String message) {
        System.out.println("[EMAIL] " + message);
    }
}

(Same structure for SMSNotifier and AppPushNotifier.)

Everything works fine—until a new requirement comes in...


⚠️ Example 2 – Adding a New Method to Interface

We need to support scheduled notifications, so we add a method to the interface:

void scheduleNotification(String message, LocalDateTime scheduleTime);

Now, all implementing classes must override this new method, or a compile error occurs.

This breaks:

  • Internal classes
  • Classes from third-party libraries
  • Any code that implements Notifier but hasn’t updated yet

This is a backward compatibility problem.


✅ Example 3 – Fixing with Default Method

We fix it by providing a default implementation for the new method:

default void scheduleNotification(String message, LocalDateTime scheduleTime) {
    System.out.println("[Default Scheduling] message: " + message + ", time: " + scheduleTime);
}

Now:

  • EmailNotifier can override it with custom behavior
  • SMSNotifier, AppPushNotifier can skip implementing it and use the default

📘 What Are Default Methods?

Default methods allow method definitions (bodies) inside interfaces, which were previously not allowed.

Purpose:

  • Define shared logic in an interface
  • Avoid breaking existing implementations

Syntax:

public interface MyInterface {
    void existingMethod();

    default void newMethod() {
        System.out.println("This is a new default method.");
    }
}

Before Java 8:

  • All methods in interfaces were abstract
  • Only method signatures, no implementations allowed

🧠 Benefits of Default Methods

✅ Backward Compatibility

  • Allows new functionality in interfaces without breaking existing code

✅ Extending Standard Libraries

  • Java's standard interfaces (List, Collection, etc.) can now evolve

✅ Lambda & Stream API Support

  • Enables interfaces to offer methods like stream(), forEach(), etc.

⚠️ Best Practices and Caveats

1. Use Only When Necessary

  • Use default methods mainly to preserve backward compatibility
  • Avoid overusing them just for convenience

2. Interfaces Should Stay Abstract

  • Interface = contract
  • Avoid putting complex logic in interfaces

3. Multiple Inheritance Conflict

  • If two interfaces have the same default method signature, the implementing class must resolve the conflict:
interface A {
    default void hello() { System.out.println("Hello from A"); }
}

interface B {
    default void hello() { System.out.println("Hello from B"); }
}

public class MyClass implements A, B {
    @Override
    public void hello() {
        // Conflict resolution here
        A.super.hello(); // or B.super.hello();
    }
}

4. Don’t Maintain State

  • Default methods should not maintain internal state
  • If state is needed, use a class instead

📝 Summary

Feature Description
Introduced Java 8
Purpose Add new interface methods without breaking old code
Syntax default keyword with method body
Override? Optional – if not overridden, default is used
Good For Backward compatibility, common simple logic
public interface MyInterface {
    void existingMethod();
    default void newMethod() {
        System.out.println("New default method");
    }
}

🚨 Final Tips

  • ✅ Use for library evolution
  • ✅ Provide simple default behavior
  • ❌ Avoid complex logic or shared state
  • ❌ Don’t overuse – keep interfaces clean

'JAVA' 카테고리의 다른 글

Exception  (0) 2025.04.16
Java Parallel Stream and Fork/Join Pattern  (0) 2025.04.04
Java Optional  (0) 2025.04.04
Java Method Reference  (0) 2025.04.02
Java Functional Interfaces  (0) 2025.04.01