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)); // 8Functional 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
EasyLet'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@FunctionalInterfaceannotation to ensure it stays functional. Your interface should declare a single abstract method calledtransformthat 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 aStringTransformerand a constructor to initialize it. Include a method calledprocess(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, orreverse).Based on the operation type, create a
TextProcessorwith the appropriate lambda:upper: transforms text to uppercaselower: transforms text to lowercasereverse: reverses the text (hint: useStringBuilder)
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)); // 8Functional 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]"
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System