Menu
Coddy logo textTech

Default & Static in Interface

Part of the Object Oriented Programming section of Coddy's Java journey — lesson 37 of 87.

Originally, interfaces could only contain abstract methods with no implementation. Starting with Java 8, interfaces gained the ability to include default methods and static methods, making them more flexible.

A default method provides an implementation directly in the interface using the default keyword. Classes that implement the interface inherit this behavior automatically but can override it if needed:

public interface Drawable {
    void draw();
    
    default void display() {
        System.out.println("Displaying on screen...");
        draw();
    }
}

Any class implementing Drawable gets the display() method for free. This is particularly useful for adding new methods to existing interfaces without breaking classes that already implement them.

Static methods in interfaces work like static methods in classes. They belong to the interface itself and are called using the interface name:

public interface MathOperations {
    static int add(int a, int b) {
        return a + b;
    }
}

// Usage
int result = MathOperations.add(5, 3);

Static interface methods cannot be overridden and are not inherited by implementing classes. They're useful for utility methods related to the interface's purpose.

If a class implements two interfaces with the same default method signature, the class must override that method to resolve the conflict.

challenge icon

Challenge

Easy

Let's build a messaging system that showcases both default and static methods in interfaces. You'll create an interface with built-in functionality that implementing classes can use directly or customize as needed.

You'll organize your code across four files:

  • Messenger.java: Define an interface that represents any messaging service. It should declare an abstract method sendMessage(String message) that returns void. Add a default method called sendWithTimestamp(String message) that prints: [TIMESTAMP] followed by calling sendMessage(message). Also include a static method called formatMessage(String message) that returns the message converted to uppercase.
  • EmailMessenger.java: Create a class that implements Messenger. It has a recipient field (String). Include a constructor to initialize the recipient. Implement sendMessage() to print: Email to [recipient]: [message]. This class uses the default sendWithTimestamp() method as-is.
  • SMSMessenger.java: Create another class that implements Messenger. It has a phoneNumber field (String). Include a constructor to initialize the phone number. Implement sendMessage() to print: SMS to [phoneNumber]: [message]. Override the default sendWithTimestamp() method to print: [URGENT] followed by calling sendMessage(message) instead of using the default timestamp behavior.
  • Main.java: Bring everything together to demonstrate both default and static interface methods. You'll receive three inputs: an email recipient, a phone number, and a message. First, use the static method Messenger.formatMessage() to format the message and store it. Then create an EmailMessenger and an SMSMessenger. For each messenger, call sendWithTimestamp() with the formatted message—notice how the EmailMessenger uses the default implementation while SMSMessenger uses its overridden version.

You will receive three inputs: the email recipient (String), the phone number (String), and the message (String).

Your output should show four lines total—two for each messenger. The EmailMessenger will show the default timestamp prefix, while the SMSMessenger will show its custom urgent prefix. Both will use the statically formatted (uppercase) message!

Cheat sheet

Starting with Java 8, interfaces can include default methods and static methods in addition to abstract methods.

Default methods provide an implementation directly in the interface using the default keyword. Classes that implement the interface inherit this behavior automatically but can override it if needed:

public interface Drawable {
    void draw();
    
    default void display() {
        System.out.println("Displaying on screen...");
        draw();
    }
}

Static methods in interfaces belong to the interface itself and are called using the interface name. They cannot be overridden and are not inherited by implementing classes:

public interface MathOperations {
    static int add(int a, int b) {
        return a + b;
    }
}

// Usage
int result = MathOperations.add(5, 3);

If a class implements two interfaces with the same default method signature, the class must override that method to resolve the conflict.

Try it yourself

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Read inputs
        String emailRecipient = scanner.nextLine();
        String phoneNumber = scanner.nextLine();
        String message = scanner.nextLine();
        
        // TODO: Use Messenger.formatMessage() to format the message and store it
        
        // TODO: Create an EmailMessenger with the email recipient
        
        // TODO: Create an SMSMessenger with the phone number
        
        // TODO: Call sendWithTimestamp() on the EmailMessenger with the formatted message
        
        // TODO: Call sendWithTimestamp() on the SMSMessenger with the formatted message
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming