Mastering Java 8 Functional Interfaces: Cleaner Code with Function, Supplier, Consumer & Runnable
This article explains Java 8's functional interfaces—including Function, Supplier, Consumer, and Runnable—showing how to replace verbose if‑else and exception handling with concise lambda expressions, and provides reusable utility interfaces for branching, present‑or‑else logic, and exception throwing.
Function Functional Interface
In Java 8 an interface annotated with @FunctionalInterface that contains exactly one abstract method can be used as a lambda expression. The most common functional interfaces are Supplier (no arguments, returns a value), Consumer (accepts a value, returns nothing), Function (accepts a value and returns a result), and Runnable (no arguments, no return).
Using Small Tricks: Handling Exceptions in if
Instead of writing repetitive if…else… blocks that throw exceptions or perform different actions, you can define custom functional interfaces and return lambda implementations that encapsulate the branching logic.
/**
* Throw exception interface
*/
@FunctionalInterface
public interface ThrowExceptionFunction {
/**
* Throw an exception with the given message
*/
void throwMessage(String message);
}Utility method that returns a ThrowExceptionFunction which throws a RuntimeException when the supplied boolean is true:
public static ThrowExceptionFunction isTrue(boolean b) {
return (errorMessage) -> {
if (b) {
throw new RuntimeException(errorMessage);
}
};
}Branch Handling Interface
/**
* Branch handling interface
*/
@FunctionalInterface
public interface BranchHandle {
/**
* Execute one of two {@code Runnable} actions based on the boolean value
*/
void trueOrFalseHandle(Runnable trueHandle, Runnable falseHandle);
}Utility method that returns a BranchHandle implementation:
public static BranchHandle isTrueOrFalse(boolean b) {
return (trueHandle, falseHandle) -> {
if (b) {
trueHandle.run();
} else {
falseHandle.run();
}
};
}Present‑Or‑Else Handling Interface
/**
* Handle present or empty values
*/
public interface PresentOrElseHandler<T> {
/**
* Execute {@code action} when the value is present, otherwise run {@code emptyAction}
*/
void presentOrElseHandle(Consumer<? super T> action, Runnable emptyAction);
}Utility method that returns a handler for a {@code String} value:
public static PresentOrElseHandler<String> isBlankOrNoBlank(String str) {
return (consumer, runnable) -> {
if (str == null || str.isEmpty()) {
runnable.run();
} else {
consumer.accept(str);
}
};
}Conclusion
Java 8 functional interfaces are a powerful feature that can dramatically simplify branching, exception handling, and null‑checking code. By defining small, reusable functional interfaces and returning lambda implementations, developers can write cleaner, more expressive backend code.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
