Guava Optional as method argument for optional par

2020-02-09 05:43发布

问题:

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

回答1:

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).