Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Valid usage of Optional type in Java 8

Is this a valid (intended) usage of Optional type in Java 8?

String process(String s) {
    return Optional.ofNullable(s).orElseGet(this::getDefault);
}
like image 675
Łukasz Rzeszotarski Avatar asked Dec 24 '15 05:12

Łukasz Rzeszotarski


People also ask

What is the use of Optional in Java 8?

Optional is a container object used to contain not-null objects. Optional object is used to represent null with absent value. This class has various utility methods to facilitate code to handle values as 'available' or 'not available' instead of checking null values.

When should we use Optional in Java?

By the way, here is how Optional is described in the Java SE 11 documentation: “ Optional is primarily intended for use as a method return type where there is a clear need to represent 'no result,' and where using null is likely to cause errors.

Why do we use Optional in Java 8 Give Explanation using a real life example?

By using Optional, you can specify alternative values to return when something is null. For example, if you have an Employee Object and it has yet to assign a department, instead of returning null, you can return a default department.


3 Answers

I'll take another swing at this.

Is this a valid usage? Yes, in the narrow sense that it compiles and produces the results that you're expecting.

Is this intended usage? No. Now, sometimes things find usefulness beyond what they were originally for, and if this works out, great. But for Optional, we have found that usually things don't work out very well.

Brian Goetz and I discussed some of the issues with Optional in our JavaOne 2015 talk, API Design With Java 8 Lambdas and Streams:

  • link to video
  • link to slides

The primary use of Optional is as follows: (slide 36)

Optional is intended to provide a limited mechanism for library method return types where there is a clear need to represent "no result," and where using null for that is overwhelmingly likely to cause errors.

The ability to chain methods from an Optional is undoubtedly very cool, and in some cases it reduces the clutter from conditional logic. But quite often this doesn't work out. A typical code smell is, instead of the code using method chaining to handle an Optional returned from some method, it creates an Optional from something that's nullable, in order to chain methods and avoid conditionals. Here's an example of that in action (also from our presentation, slide 42):

// BAD
String process(String s) {
    return Optional.ofNullable(s).orElseGet(this::getDefault);
}

// GOOD
String process(String s) {
    return (s != null) ? s : getDefault();
}

The method that uses Optional is longer, and most people find it more obscure than the conventional code. Not only that, it creates extra garbage for no good reason.

Bottom line: just because you can do something doesn't mean that you should do it.

like image 66
Stuart Marks Avatar answered Oct 12 '22 04:10

Stuart Marks


Since this is more or less an opinion-based question, I'll throw mine in. If you're trying to say

if (id == 1) {
    Foo f = new Foo(id, "Bar", "US");
    return "Bar".equals(f.getName()) && "US".equals(f.getCountryCode());
} else {
    return false;
}

then just say that. Making things "functional" doesn't automatically make things clearer or better. By introducing a needless Optional, a couple lambdas, and some Optional methods that I had to look up, you've made the code more convoluted and difficult to understand. I don't think the designers of Java "intended" for people to use Optional to help make code more obscure.

EDIT: After reading some responses, I think it's worth adding some comments. This is not a functional programming idiom I'm familiar with, which would make it harder to understand. The idioms I am familiar with mostly involve Java streams, or (in other languages) functional idioms applied to multiple values in arrays or lists or other collections of multiple values. In those cases, once you get past the unfamiliarity, the functional syntax can be seen as an improvement because it allows some details to be hidden (loop indexes, iterators, running pointers, accumulator variables). So overall, it can simplify things. This example, by itself, doesn't do any such simplification.

However, some of the Optional features are useful in stream contexts. Suppose we had a parseInt() method that returns an Optional<Integer>, which is empty if the input string is invalid. (Java 8 really should have provided this.) This would make it easy to take an array of strings and produce an array of integers in which the strings that don't parse are simply eliminated from the result--use parseInt in a stream map(), and use a stream filter to filter out the empty Optionals. (I've seen multiple StackOverflow questions asking how to do this.) If you want to keep only the positive values, you could use an Optional.filter() to change the nonpositives to Optional.empty() before using the stream filter (although in this case, you could add another stream filter afterwards, but in a more complex case the Optional filter could be more useful). That's what I see as the main benefit of Optional from a functional standpoint. It allows you to work with a collection of values all at once, by giving you a way to represent "non-values" and write a function that will still work with them. So I guess the main use of Optional, besides a replacement for null, would be to represent empty spaces in a sequence of values while you're applying functions to the entire sequence as a whole.

like image 35
ajb Avatar answered Oct 12 '22 04:10

ajb


Asking whether it's "valid" is rather opinion-based, but as to whether it's the intended use case: no, it's not.

Brian Goetz, Oracle's language architect for Java, has stated that the use case for Optional is for when you need a "no value" marker, and when using null for this is likely to cause errors. Specifically, if a reasonable user of your method is not likely to consider the possibility that its result is null, then you should use Optional. It was explicitly not intended to be a general "Maybe"-type object, as you're using it here.

In your case, the method that returns the Optional is private. That means it can only be used by the implementers of the class, and you can assume that they have good knowledge of the class' methods — including which of them may return null. Since there's no reasonable risk of confusion, Brian Goetz would (probably) say that he would not consider this a valid use case.

like image 21
yshavit Avatar answered Oct 12 '22 05:10

yshavit