How to Replace Cluttered if…else… with Java 8 Functional Interfaces

Learn how to eliminate repetitive if…else… statements in Java by leveraging Java 8’s functional interfaces—such as Supplier, Consumer, Runnable, and custom Function interfaces—through clear examples, code snippets, and step‑by‑step guidance for defining, implementing, and using these interfaces to simplify exception handling and branch logic.

Java Interview Crash Guide
Java Interview Crash Guide
Java Interview Crash Guide
How to Replace Cluttered if…else… with Java 8 Functional Interfaces

In development, if...else... statements are often used for exception throwing and branching, which can clutter code. Java 8’s Function interface can be used to eliminate such patterns.

if (...) {
    throw new RuntimeException("出现异常了");
}
if (...) {
    doSomething();
} else {
    doOther();
}

Function Functional Interface

Use the @FunctionalInterface annotation to mark an interface that contains only one abstract method. Functional interfaces are mainly divided into Supplier (providing), Consumer (consuming), Runnable (no‑arg/no‑return), and Function (with argument and return).

Function can be seen as a transformation function.

Supplier (providing) function

Supplier has no parameters and only returns data.

Supplier diagram
Supplier diagram

Consumer (consuming) function

Consumer is the opposite of Supplier. It accepts a parameter and has no return value.

Consumer diagram
Consumer diagram

Runnable (no‑arg/no‑return) function

Runnable has neither parameters nor a return value.

Runnable diagram
Runnable diagram

Function (argument and return) function

Function receives a parameter and returns a value. Supplier, Consumer and Runnable can be regarded as special forms of Function.

Function diagram
Function diagram

Tip: Handling if that throws exceptions

Define a functional interface for throwing exceptions

/**
 * Throw exception interface
 */
@FunctionalInterface
public interface ThrowExceptionFunction {
    /**
     * Throw exception message
     *
     * @param message exception message
     */
    void throwMessage(String message);
}

Write a method that returns the interface

/**
 * Returns a ThrowExceptionFunction that throws when b is true
 *
 * @param b condition
 * @return ThrowExceptionFunction
 */
public static ThrowExceptionFunction isTrue(boolean b) {
    return (errorMessage) -> {
        if (b) {
            throw new RuntimeException(errorMessage);
        }
    };
}

Usage

Call the utility method and then invoke throwMessage with an exception message. When the argument is false, execution proceeds normally.

Exception handling example
Exception handling example

When the argument is true, an exception is thrown.

Exception thrown example
Exception thrown example

Branch handling interface

/**
 * Branch handling interface
 */
@FunctionalInterface
public interface BranchHandle {
    /**
     * Branch operation
     *
     * @param trueHandle operation when true
     * @param falseHandle operation when false
     */
    void trueOrFalseHandle(Runnable trueHandle, Runnable falseHandle);
}

Method returning BranchHandle

/**
 * Returns a BranchHandle that executes different actions based on b
 *
 * @param b condition
 * @return BranchHandle
 */
public static BranchHandle isTrueOrFalse(boolean b) {
    return (trueHandle, falseHandle) -> {
        if (b) {
            trueHandle.run();
        } else {
            falseHandle.run();
        }
    };
}

Usage

When the parameter is true, trueHandle runs; otherwise falseHandle runs.

True branch
True branch
False branch
False branch

PresentOrElseHandler for optional values

public interface PresentOrElseHandler<T extends Object> {
    /**
     * Execute action when value is present, otherwise execute emptyAction
     *
     * @param action consumer for non‑null value
     * @param emptyAction runnable for null value
     */
    void presentOrElseHandle(Consumer<? super T> action, Runnable emptyAction);
}

Method returning PresentOrElseHandler

public static PresentOrElseHandler<?> isBlankOrNoBlank(String str) {
    return (consumer, runnable) -> {
        if (str == null || str.length() == 0) {
            runnable.run();
        } else {
            consumer.accept(str);
        }
    };
}

Usage

Pass a Consumer and a Runnable to handle non‑empty and empty cases respectively.

Non‑empty handling
Non‑empty handling

When the parameter is empty, the runnable executes.

Empty handling
Empty handling

Function functional interfaces are a crucial feature of Java 8; using them effectively can greatly simplify code.

JavaLambdaFunctional Interfacebranching
Java Interview Crash Guide
Written by

Java Interview Crash Guide

Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.