Explain Codes LogoExplain Codes Logo

Java 8 Lambda function that throws exception?

java
lambda
try-catch
functional-interfaces
Nikita BarsukovbyNikita Barsukov·Jan 9, 2025
TLDR

To handle exceptions within Java 8 Lambdas, craft a custom @FunctionalInterface. Here is a no-nonsense illustration:

@FunctionalInterface public interface ThrowingSupplier<T, E extends Exception> { T get() throws E; } // Now, ready to juggle an IOException without fear! ThrowingSupplier<String, IOException> riskySupplier = () -> { // 🎱 Magic 8-Ball says... "Reply hazy, try again" if (new Random().nextBoolean()) throw new IOException("Random hiccup"); return "Smooth sailing"; };

This smart pattern aids in using checked exceptions within your lambdas with no disruption.

Play it safe with try-catch

If custom functional interfaces seem too alien, resort to our trusty try-catch blocks right within the lambda expressions.

Supplier<String> wrappedSupplier = () -> { try { // Walked under a ladder? Get ready for some bad luck. return riskyOperation(); } catch (Exception e) { throw new RuntimeException(e); } }; String result = wrappedSupplier.get();

In this instance, riskyOperation represents a daring method call ready to throw a checked exception.

Extending Java's standard functional interfaces

A quick fix to handle exceptions requires extending Java 8's functional interfaces. Let's extend Consumer and see the magic unfold.

@FunctionalInterface public interface ThrowingConsumer<T, E extends Exception> extends Consumer<T> { void acceptThrows(T t) throws E; @Override default void accept(T t) { try { acceptThrows(t); } catch (Exception e) { throw new RuntimeException(e); // "Exception dodged!" - The Lambda 🦖 } } }

Putting Durian library to work

No need to reinvent the wheel! Durian library provides the Errors utility to convert thrown exceptions to unchecked and simplifies your lambda usage.

import com.diffplug.common.base.Errors; Supplier<String> supplierWithRethrow = Errors.rethrow().supplier(() -> { // "Clear the path! Exception incoming!" - The Lambda 🦸‍♀️ return "Result"; });

This cool pattern uses Durian's Errors to wrap the lambda expression and apply an impressive error handling policy.

Pairing method references with exceptions

When using method references that aren't afraid of exceptions, you can wrap them in a custom functional interface for a clean syntax.

Function<Path, String> readFile = Unchecked.function(Files::readString); // "Try me!" - Files::readString

Here, Unchecked.function could be similar to Durian's utility methods, essentially castling checked exceptions for unchecked ones.

Specialized interface for IOException

Specialize a custom functional interface for frequent exceptions like IOException.

@FunctionalInterface public interface IOFunction<T, R> extends Function<T, R> { R apply(T t) throws IOException; static <T, R> Function<T, R> unchecked(IOFunction<T, R> function) { return t -> { try { return function.apply(t); } catch (IOException e) { throw new UncheckedIOException(e); } }; } }

Leverage IOFunction.unchecked to allow lambdas plagued with IOException to fit into the more generic environment of Function<T, R>.

Enforcing error handling policies

Establish fail-safe error handling policies that take over during exception scenarios.

Consumer<String> consumerWithDefaultValue = s -> { try { process(s); } catch (Exception e) { logError(e); // "Captain, we encountered an error!" - The Lambda // Default action or value takes center stage } };

The agreed policy here is to log the menacing error and provide a default action rather than allowing the exception to escalate.

Some handy references

  1. Lambda Expressions (The Java™ Tutorials) — Here is your guide to understanding the vital elements of lambda expressions in Java.
  2. Method References (The Java™ Tutorials) — Dive deeper into method references that can be used alongside lambdas in Java.
  3. Java 8: Lambda-Streams, Filter by Method with Exception - Stack Overflow — Gain additional insights into manhandling exceptions during lambda stream operations.
  4. How to Handle Checked Exceptions With Lambda Expression - DZone — Learn how to wrap exceptions within lambdas and maintain a clean codebase.
  5. Java 8 Lambda : Consumer Example — Learn how the Consumer interface aids in lambda expressions with a detailed tutorial.
  6. Java Sneaky Throws — The "sneaky throws" technique allows handling of checked exceptions in a sly method without declaring them.