Menu
Coddy logo textTech

Functional Interfaces

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

A functional interface is an interface that contains exactly one abstract method. This single-method constraint makes functional interfaces special because they can be implemented using lambda expressions, enabling a more concise coding style.

Java provides the @FunctionalInterface annotation to explicitly mark an interface as functional. While optional, this annotation helps the compiler catch errors if you accidentally add a second abstract method:

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
}

You can implement a functional interface the traditional way with a class, or more concisely with a lambda expression:

// Traditional implementation
Calculator adder = new Calculator() {
    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
};

// Lambda expression (much shorter!)
Calculator adder = (a, b) -> a + b;

System.out.println(adder.calculate(5, 3));  // 8

Functional interfaces can still have default methods and static methods since those don't count toward the single abstract method rule. Java's java.util.function package provides many built-in functional interfaces like Predicate, Function, and Consumer that you'll encounter frequently when working with streams and collections.

challenge icon

Challenge

Easy

Let's build a string transformation system using functional interfaces and lambda expressions. You'll create a flexible text processor that can apply different transformations to strings—all powered by a single functional interface.

You'll organize your code across three files:

  • StringTransformer.java: Define a functional interface that represents any string transformation operation. Mark it with the @FunctionalInterface annotation to ensure it stays functional. Your interface should declare a single abstract method called transform that takes a String and returns a String.
  • TextProcessor.java: Create a class that uses your functional interface to process text. It should have a field to hold a StringTransformer and a constructor to initialize it. Include a method called process(String text) that applies the transformer to the given text and returns the result. This design lets you inject any transformation behavior through the constructor.
  • Main.java: Bring everything together by creating different transformations using lambda expressions. You'll receive two inputs: a text string and an operation type (upper, lower, or reverse).

    Based on the operation type, create a TextProcessor with the appropriate lambda:

    • upper: transforms text to uppercase
    • lower: transforms text to lowercase
    • reverse: reverses the text (hint: use StringBuilder)

    Then call process() with the input text and print the result in this format: Result: [transformed text]

You will receive two inputs: the text to transform (String) and the operation type (String).

Notice how the same TextProcessor class can perform completely different operations depending on which lambda you pass in—that's the power of functional interfaces!

Cheat sheet

A functional interface is an interface with exactly one abstract method. It can be implemented using lambda expressions for concise code.

Use the @FunctionalInterface annotation to mark an interface as functional (optional but recommended):

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
}

Functional interfaces can be implemented traditionally or with lambda expressions:

// Traditional implementation
Calculator adder = new Calculator() {
    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
};

// Lambda expression
Calculator adder = (a, b) -> a + b;

System.out.println(adder.calculate(5, 3));  // 8

Functional interfaces can have default and static methods without violating the single abstract method rule.

Java's java.util.function package provides built-in functional interfaces like Predicate, Function, and Consumer.

Try it yourself

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String text = scanner.nextLine();
        String operation = scanner.nextLine();
        
        TextProcessor processor;
        
        // TODO: Based on the operation type, create a TextProcessor with the appropriate lambda:
        // - "upper": transforms text to uppercase
        // - "lower": transforms text to lowercase
        // - "reverse": reverses the text (hint: use StringBuilder)
        
        // TODO: Call process() with the input text and print the result
        // Output format: "Result: [transformed text]"
    }
}
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