Skip to content

treestack/throwing

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Throwing functional interfaces

Maven CI/CD Coverage License

Introduction

Java 8 introduced the concept of functional interfaces—interfaces that have only one abstract method. It also introduced lambda expressions, which allow for concise implementations of functional interfaces.

However, a significant limitation of Java's standard java.util.function interfaces is that they do not handle checked exceptions well. If you need to use a method that throws a checked exception within a lambda expression, you must wrap the method call in a try-catch block.

This leads to unnecessary boilerplate. What could have been a simple expression like this:

Stream.of("foo", "bar")
    .map(s -> s.getBytes(StandardCharsets.UTF_8));

quickly turns into:

Stream.of("foo", "bar")
        .map(s -> {
            try {
                return s.getBytes(StandardCharsets.UTF_8);
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        });

This project provides a set of functional interfaces that support checked exceptions, allowing for cleaner and more readable code.

⚠ Note: Before reading further, if your project uses a fairly recent version of Spring, check the org.springframework.util.function package. It contains similar classes with overlapping functionality, which might eliminate the need for an additional dependency.

Status

The following functional interfaces are currently provided by this project:

Installation

To use this library, add the following dependency to your project:

Maven

<dependency>
    <groupId>de.treestack</groupId>
    <artifactId>throwing</artifactId>
    <version>1.2.0</version>
</dependency>

Gradle

dependencies {
    implementation("de.treestack:throwing:1.2.0")
}

Unchecked exceptions

The unchecked() method is a utility that wraps methods throwing checked exceptions in a lambda expression that instead throws an unchecked exception.

⚠ Note: The unchecked() method wraps any thrown checked exception in a RuntimeException, setting the original exception as its cause.

Example

import static de.treestack.throwing.Function.unchecked;

Stream.of("foo", "bar")
    .map(unchecked(s -> s.getBytes(StandardCharsets.UTF_8)));

Lifted functional interfaces

Instead of using unchecked(), you can use the lifted functional interfaces provided by this project. These are similar to the standard functional interfaces in java.util.function, but instead of throwing an exception, they return an Optional.

⚠ Note: If an exception is thrown, the lifted functional interfaces return an empty Optional, meaning the original exception is lost.

Example

Because the lifted functional interfaces return an Optional, you can use the flatMap method to chain operations that may fail.

import static de.treestack.throwing.Function.lifted;

// Using a static method reference

Optional<MyObject> bytes = Optional.of("some-id")
        .flatMap(lifted(myService::findById));

// Using a lambda function

Optional<byte[]> bytes = Optional.of("foo")
    .flatMap(lifted(s -> s.getBytes(StandardCharsets.UTF_8)));

If an operation is not supposed to fail, or you just don't care about the exception, you can also wrap a method reference in a lifted function and call it directly:

import static de.treestack.throwing.Function.lifted;

Optional<String> name = lifted(myService::findById).apply(id)
    .map(MyEntity::getName);

License

This project is licensed under the MIT License. See the LICENSE file for details.

About

Support for checked exceptions in Java 8+ functional interfaces

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages