

What's more, throwing an exception would require that we catch the exception in the calling code in order to create the default. It is possible for the developer to throw an exception when the value cannot be found, but a missing value may not be a case that warrants an exception (i.e., it may not be an exceptional case).įor instance, if we want to check if an object exists already, or create one if it does not, a non-existent object would not be an error and throwing an exception would not be warranted. This client-responsible approach means that the method developer does not have enough information to determine what should be done in the case of a missing value. Thus, the client is now responsible for handling the case when no result is found (i.e., one of the Optional methods, such as orElse, must be called to get from Optional to Foo). In essence, the doSomething method-by nature of returning Optional rather than Foo-is telling the client that there is a possibility that a result will not be found. This brings us to note (2): The responsibility for handling the empty Optional rests upon the client. Since both of those methods require a parameter, they, therefore, require us to make an explicit decision about what default value to use or what exception to throw if the Optional is empty. Thus, we must call a method such as orElse or orElseThrow-or get, but we will see later why that should not be the first choice-in order to convert the Optional object to a Foo object. We will instead see a compilation error alerting us that an object of type Optional cannot be cast to Foo since the return type of doSomething is Optional and the type of foo is Foo. Therefore, if we know that our doSomething method may not return a desired Foo object, we can change the signature to: This class acts as a wrapper for an object that may not be present. This mechanism was introduced in Java Development Kit (JDK) 7 in the form of the Optional class.

Instead, we need a mechanism that allows a method developer to explicitly denote that the return value for a method may or may not be present. Similarly, annotations like exist, but these suffer from the same drawback as the documentation approach. While this is an improvement over the original problem, this does not ensure that a client checks for nullity prior to the use of the object (i.e., the Java compiler will compile the code without these null-checks without complaint). One solution that is commonly used is documenting that a return value can be null using JavaDocs. Since we are unsure, we are forced to assume that any returned object can be null. The root problem is that we do not know when a method intends to return null-such as when a desired value cannot be found-or can contractually guarantee that null will never be returned. For example, adding extra lines for null-checks would introduce boilerplate code throughout our application that makes the use of the Foo object less clear (hidden within an if- else statement). It goes without saying that this would not only be infeasible in a large application, but it would also muddle the clarity of our code. Thus, exhaustively, we must check every object returned from a method for nullity prior to using it. This creates another problem, though: A ny non-primitive object can be implicitly set to null. This approach ensures that the use of the Foo object does not result in a NullPointerException (NPE).
