'How can I return an optional instead of throwing an exception?
I have a method that can possibly throw an error. This exception is out of my control, as it is an IO exception, not a exception I am throwing. Instead of adding a throws statement to my method or fitting it in a try and catch block, would I be able to return an optional via this method?
Summary: I have a method to return a value T, except to get to that value, I have to add a try/catch block or throws statement to my method. Can I return an Optional of type T instead of throwing this error?
Solution 1:[1]
You can use code like this to wrap code that returns a value with something that captures exceptions and returns an empty optional:
import java.util.Optional;
import java.util.function.Supplier;
@FunctionalInterface
public interface ThrowingSupplier<T> extends Supplier<Optional<T>> {
@Override
default Optional<T> get() {
return getCapturingExceptions(this);
}
T getOrThrow() throws Exception;
static <U> Optional<U> getCapturingExceptions(ThrowingSupplier<U> supplier) {
try {
return Optional.ofNullable(supplier.getOrThrow());
} catch (Exception e) {
e.printStackTrace();
return Optional.empty();
}
}
}
Examples of use:
import org.junit.Test;
import java.util.Optional;
import static org.junit.Assert.assertEquals;
public class ThrowingSupplierTest {
@Test
public void testSuccessfulSupplier() {
assertEquals(
Optional.of("Successful"),
ThrowingSupplier.getCapturingExceptions(() -> "Successful")
);
}
@Test
public void testThrowingSupplier() {
assertEquals(
Optional.empty(),
ThrowingSupplier.getCapturingExceptions(() -> {
throw new Exception("Expected failure; will be logged but test should pass");
})
);
}
}
This has all of the disadvantages outlined in Jim Garrison's answer, and I would agree with him that it is usually better to allow exceptions to propagate (wrapping in an unchecked exception when necessary). Still, this is sometimes useful. For example, if you need to implement an interface that doesn't allow for a checked exception, and allowing an unchecked exception to propagate up the call stack would have undesirable effect such as killing a thread that doesn't handle them properly. To that end, this example implements Supplier (which cannot throw an unchecked exception) and can be used anywhere that interface is expected.
A few changes you might want to make:
This logs caught exceptions using
e.printStackTrace(). It is important not to completely lose the exception message and stack trace, but if your application uses a logging framework, you might prefer to log the exception using that.It uses
Optional.ofNullableon the assumption that the wrapped code might returnnull, which isn't allowed in anOptional. This means that it might return an emptyOptionaleven if no exception occurred. If the original code is not expected to returnnull, this could be changed toOptional.of. However if the wrapped code does returnnullin that case,Optional.ofwill throw aNullPointerException, which will be caught by thecatchblock and result in an emptyOptionalreturned regardless.
It should also be noted that if the wrapped code returns an Optional type itself, this will be wrapped in another Optional layer. Getting the underlying value will require unwrapping it twice.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Tim Moore |
