Java Reference
In-Depth Information
* @param exceptionHandler The handler for exceptions; never {@code null}j
* @param exceptionClasses The classes being handled by this handler;
* never {@code null}
* @return {@code this} for chaining
*/
public <EXCEPTION_T extends Exception> Result<RESULT_T> whenException(
Consumer<? super EXCEPTION_T> exceptionHandler,
Class<? extends EXCEPTION_T>... exceptionClasses
) {
Objects.requireNonNull(exceptionHandler, "exception handler");
Objects.requireNonNull(exceptionClasses, "exception classes to handle");
exception.ifPresent(e -> {
Stream<Class<? extends EXCEPTION_T>> classesStream =
Stream.of(exceptionClasses);
Optional<Class<? extends EXCEPTION_T>> match = classesStream.filter(
c -> c.isInstance(e)
).findAny();
match.ifPresent(exceptionClass -> {
EXCEPTION_T ex = exceptionClass.cast(e);
exceptionHandler.accept(ex);
}
);
}
);
return this;
}
}
The first things to note are the constructors and the accessors: the class encapsulates two Optional
instances: one representing the result, and one representing the exception that was thrown. A given result
can either be a result or an exception that was thrown, so one of these will be the empty optional and the
other one will be populated.
The hasResult() method shows a common theme. It simply delegates to the result.isPresent()
method, and this class will regularly end up simply delegating to the appropriate Optional instance method.
In this case, we check if we have a result by checking if the result is present.
The getOrDie() method provides a convenient way for us to get at the result if we really know that the
result is present. If the caller is wrong and the result is not present, it will throw a NoSuchElementException
with the resulting exception as a suppressed exception. This is implemented via the orElseThrown
method, which either returns the result or throws the exception provided by a Supplier . Our Supplier
implementation will put the exception into the stack trace of the NoSuchElementException , which should
help debugging. (The “INTERNAL ERROR” exception is only ever reached if both the exception and the result
were initially populated as null , which should simply never happen.)
The map function will transform the result, if it exists; otherwise, it will construct a new result and pass
the exception along. This creates a way to act upon the result without losing the exception information. In
most case when you reach for getOrDie() , you really want map() .
The ifPresent and ifNotPresent methods provide a convenient way to consume the result or the
exception if they are present. This, along with map() , allows the user to specify an implementation without
having to worry about the state of the result, which makes for a very readable API. Note that the big
difference with ifPresent() / ifNotPresent() and map() is the return value: ifPresent() / ifNotPresent()
loses information but converts to the more common Optional type, while map() retains information but
stays with the present type.
 
Search WWH ::




Custom Search