This will be a controversial topic, and I am sure that not all will agree with me. There is a debate in the Java community related to the Optional object and whether it should be used only as output or if it can be used as input as well. While most people advocate for only using Optional as output, including some big names from the Java ecosystem, a few don’t agree with them.
In most cases, the presence of an optional parameter in the method signature can pose problems. Still, I believe that a few scenarios were not only using it as input is not only acceptable but recommended. Hopefully, by the end of this article, you will see the advantage of using it as well. And, as with most things in life, don’t overuse it.
Let’s look at the following scenario. You have a complex object, let’s call it Person, that holds some data: first name, last name, age, gender, year of birth, and so on. For simplicity, I won’t write the getter and setter methods.
Just a simple data class that can be modeled as an Entity or a DTO. Nothing fancy for now, but keep in mind possible scenarios of receiving this object as an output from a source.
Next, we have a data source with all the Persons available to the system alongside a method that returns them. However, we don't always want ALL of them; we want to filter the results by name, gender, age, or combination of these three. And this is where the use of an Optional as an input will add value to the code and make understanding the API easier.
We filter the List's stream for each filtering parameter that we want and return the remaining items—something like the code below. Keep in mind that it was simplified for clarity.
The power does not stay in the fact that Optional makes the code better, but in the fact that just by reading the method's signature, you know that it will work just fine regardless of what input parameter combination you use. Only need the ones that are 32 years old? Not a problem. Want those that are also named Popescu? Just provide it!
Yes, you could use it without Optional and do null-checks, however as an external developer, you would have to look over the method's implementation or documentation to know that you don't need all of them and that it will work with any combination. Furthermore, this way, you don't have to write overloaded methods for every variety of possible filtering options.
And I know what you are thinking: Nobody filters an Array this way. First, you would be surprised. And secondly, imagine that instead of having a Data Source that filters a list, you have a Specification that builds a Query using the CriteriaBuilder. This query is later passed to the DB for returning the actual data, just like in the example below.
In this example, for building the predicate, we are using an abstract JPAFilter class that has the utility methods for building predicates, like "equal," "and," "like" and "or" predicates. Furthermore, since PersonSpecification implements the Spring Data Specification, it can be used in queries for retrieving the information from the database.
A similar situation is in Spring's RequestParam attributes where non-mandatory ones are Optional, clearly indicating just by looking over the method's signature which parameters are optional and which aren't.
Now, just because Optional exists does not mean you should be using it all the time. Indeed, in most situations having it as input can signify that there is something wrong with the overall architecture of the service or class. But nothing is truly black or white. Hopefully, I managed to convince you that there are situations when using Optional as an input parameter that can help with better understanding the code without reading the documentation.