There may be times when a missing value is an error-such as when we assume a value exists and its absence could cause fatal results for the application-and a method should throw a checked or unchecked exception. Understanding this, Optional is a useful technique when a client is responsible for handling a missing object and the absence of the object is not an error. Thus, the Optional lexicon matches the intended meaning much more closely than the exception approach. In the former case, we have to consciously derive the meaning of the catch clause to be the default value when findIfExists cannot find an existing value. By simply reading the code, we understand that the two lines mean find if exists or else use this value. For example, suppose we create the following method:Īdditionally, the latter approach is much more readable. 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).
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |