Interface Result<T,E>
- Type Parameters:
T
- The type of anOk
value, meaning that the operation has completed successfully.E
- The type of anErr
value, meaning that the operation has failed with some kind of error.
Ok
, in which case it was
performed successfully and without any errors, or it can be an Err
,
meaning that something unexpected or invalid occurred. This could be anything
from a user supplying an incorrect value to a network connection closing
unexpectedly.
Normally JVM languages would handle these conditions with exceptions, but doing so can lead to control flow which is difficult to keep track of. With a result type, all conditions are covered by virtue of being correctly typed.
-
Method Summary
Modifier and TypeMethodDescriptionApply a fallible operation to the wrapped value if the result isOk
.err()
Get theErr
value if it exists.static <T,
E> Err<T, E> err
(E e) AnErr
indicates that a fallible operation has failed and yielded an error value.Return the value ifOk
, otherwise throw an exception with a custom error message.Returns the value or throws a caller-defined exception.Return the value ifErr
, otherwise throw an exception with a custom error message.Returns the value or throws a caller-defined exception.boolean
isErr()
Indicates whether the wrapped value is anErr
.boolean
isOk()
Indicates whether the wrapped value is anOk
.Apply a transformation to the wrapped value if the result isOk
.Apply a transformation to the wrapped value if the result is anErr
.void
Apply a lambda with no return type to the value of a result.<U> U
Apply a transformation to the value of a result.ok()
Get theOk
value if it exists.static <T,
E> Ok<T, E> ok
(T t) AnOk
indicates that a fallible operation has been performed successfully and that the caller has received their desired result.Apply a fallible operation to the wrapped value if the result is anErr
.tryOr
(CheckedSupplier<T, E> supplier, Class<E> cls) Attempts to execute a fallible operation and returns any exceptions thrown during execution as the error type.unwrap()
-
Method Details
-
ok
AnOk
indicates that a fallible operation has been performed successfully and that the caller has received their desired result.- Type Parameters:
T
- the type ofT
.E
- the type of any errors that the fallible operation might produce. In theOk
case this type is unused, but knowing it is important for building robust error handling.- Parameters:
t
- the output value of the fallible operation.- Returns:
- an
Ok
result wrappingt
.
-
err
AnErr
indicates that a fallible operation has failed and yielded an error value.- Type Parameters:
T
- the type of the value that the fallible operation provides on success. In theErr
case this type is unused, but knowing it is important for building robust error handling.E
- the type ofe
.- Parameters:
e
- the value of the error. This can be any object and does not need to be a subclass ofThrowable
. If an exception needs to be thrown on an error, use theunwrap
orexpect
methods.- Returns:
- an
Err
result wrappinge
.
-
isOk
boolean isOk()Indicates whether the wrapped value is anOk
.- Returns:
true
if the wrapper isOk
, otherwisefalse
.
-
isErr
boolean isErr()Indicates whether the wrapped value is anErr
.- Returns:
true
if the wrapper isErr
, otherwisefalse
.
-
ok
Get theOk
value if it exists. -
err
Get theErr
value if it exists. -
unwrap
- Returns:
- the value of
Ok
without anOptional
wrapper. - Throws:
UnwrapException
- if the result is notOk
.
-
unwrapErr
Retrieve theErr
value or throw anUnwrapException
if the result isOk
. If the error is aThrowable
, it will not be thrown. To throw a custom error, useexpect(Function)
.- Returns:
- the value of
Err
without anOptional
wrapper. - Throws:
UnwrapException
- if the result is notErr
.
-
expect
Return the value ifOk
, otherwise throw an exception with a custom error message.- Parameters:
errorMessage
- The message to accompany theUnwrapException
if thrown.- Returns:
- The value, if
Ok
. - Throws:
UnwrapException
- If the result is anErr
.
-
expect
Returns the value or throws a caller-defined exception. -
expectErr
Return the value ifErr
, otherwise throw an exception with a custom error message.- Parameters:
errorMessage
- The message to accompany theUnwrapException
if thrown.- Returns:
- The value, if
Err
. - Throws:
UnwrapException
- If the result isOk
.
-
expectErr
Returns the value or throws a caller-defined exception.- Type Parameters:
F
- Type of the thrown exception.- Parameters:
mapping
- Lambda for creating the thrown exception.- Returns:
- The value, if Err.
- Throws:
F
- Thrown if the result is Ok.
-
match
Apply a transformation to the value of a result.In the example below, the
parseArgs
function attempts to convert a user-provided string to a list of integers, but failing that returns its input unmodified. The output of the function is then used to determine the number of valid user-provided arguments and do some additional logging for convenience.
Note that unlikeResult<List<Integer>, String> parsed = parseArgs(input); int validArgs = parsed.match( ok -> ok.size(), err -> { log.warn("The provided input could not be parsed: \"{}\"", err); return 0; } );
map(Function)
, both theOk
andErr
values must be mapped to a single output type.- Type Parameters:
U
- the type of the value to be returned after the transformations are applied. Both transformations must converge to this type.- Parameters:
ifOk
- the transformation that is applied to the underlying data if the result isOk
.ifErr
- the transformation that is applied to the underlying data if the result is anErr
.- Returns:
- a value of type
U
after applying one of the two provided transformations.
-
match
Apply a lambda with no return type to the value of a result.This is useful for things which produce side effects such as logging. In contrast to
match(Function, Function)
, no output can be obtained from an invocation of this method. In the example below, some informational logging is performed on theparseArgs
function.Result<List<Integer>, String> parsed = parseArgs(input); parsed.match( ok -> log.info("args were parsed successfully: {}", ok), err -> log.warn("The provided input could not be parsed: \"{}\"", err) );
-
map
Apply a transformation to the wrapped value if the result isOk
. If the result is anErr
, no transformation will be applied.
If an exception is thrown while applyingassertEquals( 6, Result.ok(5).map(x -> x + 1).unwrap() ); assertEquals( "error", Result.<Integer, String>err("error").map(x -> x + 1).unwrapErr() );
mapping
, the exception will not be caught. Ensure that any lambda passed to this function does not throw any runtime exceptions. -
mapErr
Apply a transformation to the wrapped value if the result is anErr
. If the result isOk
, no transformation will be applied.
If an exception is thrown while applyingassertEquals( "error: 'foo'", Result.err("foo").mapErr(err -> String.format("error: '%s'", err)).unwrapErr() ); assertEquals( 5, Result.ok(5).mapErr(err -> String.format("error: '%s'", err)).unwrap() );
mapping
, the exception will not be caught. Ensure that any lambda passed to this function does not throw any runtime exceptions. -
and
Returns the provided argument if the result isOk
and propagates the originalErr
otherwise.assertEquals( Result.err("first error"), Result.err("first error").and(Result.err("second error")) ); assertEquals( Result.err("second error"), Result.ok(1).and(Result.err("second error")) ); assertEquals( Result.ok(2), Result.ok("success").and(Result.ok(2)) );
-
andThen
Apply a fallible operation to the wrapped value if the result isOk
. If the result is anErr
, the error is propagated to the next operation in the chain.This operation differs from
map
in that if the value yielded by the provided fallible operation is an error, it is returned without being wrapped in a redundant, enclosingResult
. Take, for example, two functions:getUserInput()
which returns aResult<String, RuntimeException>
andparseInt(String s)
which returns aResult<Integer, NumberFormatException>
. A chain of operations could be built up as follows:
IfResult<Integer, RuntimeException> result = getUserInput().andThen(parseInt);
map
had been used instead, the chain would have looked like:Result<Result<Integer, NumberFormatException>, NoSuchElementException> result = getUserInput().map(parseInt);
- Type Parameters:
U
- the output type ofresultFn
.- Parameters:
resultFn
- the function to be applied if the result isOk
.- Returns:
- either the output of
resultFn
or the original error.
-
or
Returns the provided argument if the result is anErr
and propagates the originalOk
value otherwise.assertEquals( Result.ok("success"), Result.err("error").or(Result.ok("success")) ); assertEquals( Result.ok("first"), Result.ok("first").or(Result.ok("second")) ); assertEquals( Result.err("second"), Result.err("first").or(Result.err("second")) );
-
orElse
Apply a fallible operation to the wrapped value if the result is anErr
. If the result isOk
, the value is propagated to the next operation in the chain.assertEquals( Result.ok("recovered from err: foo"), Result.err("foo").orElse(err -> Result.ok("recovered from err: " + err)) ); assertEquals( Result.ok("no error"), Result.ok("no error").orElse(err -> Result.ok("recovered from err: " + err)) );
-
tryOr
Attempts to execute a fallible operation and returns any exceptions thrown during execution as the error type.- Type Parameters:
T
- The type of the result value if no exception is thrown.E
- The type of the result value if an exception is thrown by the provided function/- Parameters:
supplier
- A lambda that will be evaluated at runtime to either yield a result or throw an exceptioncls
- The class than the exception will be cast to if thrown. This is required because java cannot be generic over exceptions. If the caught exception cannot be case to this class, a runtime exception will be thrown.- Returns:
- either the output of the provided supplier or a caught exception that was thrown during its evaluation.
- Throws:
ErrorTypeMismatchException
- if a caught exception cannot be cast tocls
.
-