Reputation: 6988
Recently I had a discussion with my teammate on use of Guava
Optional
for optional parameters in a method.
Let's say method is
List<Book> getBooks(String catalogId, Optional<String> categoryId) {
Validate.notNull(catalogId);
Validate.notNull(categoryId); // Point of conflict. Is this required?
which accepts a catalogId
and an optional categoryId
which returns books listed in that catalog and if category is also passed then returns books only in that category.
Point of conflict was, Validating Optional<String> categoryId
for null check. I was of view point that there should not be a null check on it since it's an optional parameter. Caller of the function can either pass null
or Optional.<String>absent()
and getBooks
function should handle both cases by doing if(categoryId==null && categoryId.isPresent())
in the implementation.
My opinion was that Optional
for optional parameters just makes the contract of the method more clear. One can tell just by looking at method signature that this parameter is optional and does not need to read the javadocs. But he should not be forced to pass Optional.absent()
when he does not want to use that optional parameter.
My team mate had different view. He wanted to put a null check for it and hence force the caller to always pass Optional.<String>absent()
. His point was that why would we pass a null optional. Moreover getBooks("catalog123", Optional.absent())
looks more readable than getBooks("catalog123", null)
.
This method is in one of our library packages and is used by multiple packages owned by us.
What are your suggestions on usage of Optional
for this scenario?
Thanks
Upvotes: 3
Views: 2795
Reputation: 46392
What are your suggestions on usage of Optional for this scenario?
Avoid. Avoid. Avoid.
While Optional
is a cool alternative to null
, in Java you'll always end up with it being a bad addition instead. As Seelenvirtuose wrote, there are three possibilities where you need only two. As JB Nizet wrote, it's best used as a return value, where it reminds the caller of the needed check. As a method argument, it doesn't help anything.
Ideally, an optional argument would be just optional like in
getBooks(String catalogId, String categoryId = null)
which is no valid Java. AFAIK the C++ compiler translates it into two methods
getBooks(String catalogId, String categoryId)
getBooks(String catalogId)
which is what you have to write in Java yourself. Leaving a parameter out is the clearest way of making clear that it's optional. Marking the optional argument as @Nullable
is nearly as good. Using a nullability checking tool can help you avoid NPEs (which is the main argument for Optional
).
What's important is consistency. Consistency across your classes is in your hands. Consistency with JDK means using null
, at least for the foreseeable future (one day JDK 8 Optional
may prevail).
Upvotes: 9