Try-Success-Failure API: Java implementation of the famous Scala counterpart

Source code: Try-Success-Failure API for Java

This API is a Java implementation of the Scala Try API, originally implemented by the guys at Twitter and later added to the Scala Standard Library.

The Try type represents a computation that may fail. If the computation succeeds, it returns the value wrapped in a Try.Success; otherwise, it returns the java.lang.Exception wrapped in a Try.Failure.

To use Try, you need to call the Try.apply(FailableSupplier) method passing in a lambda with the same signature as a standard java.util.function.Supplier. Indeed, FailableSupplier is just a java.util.function.Supplier with throws Exception added to its get method.

For example, Try can be used to perform division on a user-defined input, without having to handle exceptions explicitly everywhere they might occur.

An important property of Try shown in the divide method of the MainExample class is its ability to pipeline (chain if you prefer) operations, catching exceptions along the way thanks to its flatMap method. If you are not a seasoned functional programming geek, concepts such as flatMap/map might not be easy to grasp at first. However, you’ll get used to them and, in the end, you’ll love them. Moreover, you’re going to encounter these methods more and more often since some important Java 8 classes already implement them (e.g. java.util.Optional and java.util.stream.Stream). For now, just take for granted that to pipeline more than two operations, say N, you just need to chain them by using N - 1 flatMap calls and a final call to map. E.g.: Suppose you have 3 variables (x, y and z) of type Try and you just want to sum them up. The code you need for doing that is the following:

x.flatMap(a -> y.flatMap(b -> z.map(c -> a + b + c)))

Apart from map and flatMap, Try has many other useful methods. See the TryTest class for thorough coverage of all methods.

Usage example

System.out.println("Integer division");
System.out.println("Enter the dividend press Return and then enter the divisor: ");
Scanner dividend = new Scanner(System.in);
Scanner divisor = new Scanner(System.in);

Try<Integer> num = Try.apply(dividend::nextInt);
Try<Integer> denom = Try.apply(divisor::nextInt);

Try<Integer> result = num.flatMap(x -> denom.map(y -> x / y));
Try<String> resultTryStr = result.map(i -> "The result of division is: " + i);
String resultStr = resultTryStr.getOrElse("You must've divided by zero or entered something that's not an Int. Try again!");
System.out.println(resultStr);

In the example above, if you enter two valid integers and the second one—the divisor—is nonzero, then the code prints out The result of division is: $RESULT, where $RESULT is the result of dividing the first number by the second. On the other hand, if you enter invalid input—such as a string—or the second number is zero, you’ll get the message You must've divided by zero or entered something that's not an Int. Try again! printed out.

Anyway, as I already said, see the TryTest class for thorough coverage of all methods.

Final Notes

Any criticism or suggestions are more than welcome!

Source code: Try-Success-Failure API for Java