<a href="https://www.buymeacoffee.com/eduardoeljaiek" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy Me A Coffee" style="height: 35px !important;width: 125px !important;" ></a>
***
> Optional - The Mother of all [[What Bikeshedding is | Bikesheds]]. ~ Stuart Marks
### What is Optional meant for?
>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 to cause errors**.
>\~ Optional Javadoc
That's the main reason **I use Optional in my projects, to represent "no result" in my public APIs** or components that will be consumed outside the package they belong.
> [!WARNING] Remember, Optional is a box!
> - It is a separate object, **consumes 4x memory** of a bare reference.
> - Potentially adds [[What GC pressure is | GC pressure]].
> - Always requires a dependent load, leading to cache misses.
> - Could turn into a performance/space problem if used frequently.
>
> \~ Stuart Marks
> [!INFO] Don't replace every null with an Optional
> - [[Java - Null can be safe, if it is well controlled| null can be safe, if it's well controlled]]
> - `null` in private field can be easily checked
> - nullable parameters are ok (if [déclassé](https://www.merriam-webster.com/dictionary/d%C3%A9class%C3%A9))
> - library code should take responsibility for checking args
>
> ~ Stuart Marks
> [!HINT] Technique: unit testing a method that returns Optional
>
> ```java
> assertEquals(Optional.of("expected value"), optionalReturningMethod());
> assertEquals(Optional.empty(), optionalReturningMethod());
>```
>~ Stuart Marks
### Rules
**Rule 1:** Never, ever, use `null` for an `Optional` variable or return value.
**Rule 2:** Never use `Optional.get()` unless you can prove that the `Optional` is present.
**Rule 3:** Prefer alternatives to `Optional.isPresent()` and `Optional.get()`.
![[optional-rule2-3.png]]
**Rule 4:** It's generally a bad idea to create an `Optional` for the specific purpose of chaining methods from it to get a value.
```java
// BAD
return Optional.ofNullable(s).orElseGet(this::getDefault);
// GOOD
return (s != null) ? s : getDefault()
return Objects.requireNonNullElseGet(s, this::getDefault);
```
**Rule 5:** If an `Optional` chain is nested or has an intermediate result of `Optional<Optional<T>>`, it's probably too complex.
```java
Optional<BigDecimal> first = getFirstValue();
Optional<BigDecimal> second = getSecondValue();
// Add first and second, treating empty as zero, returning an Optional of the sum,
// unless BOTH are empty, in which case return an empty `Optional`.
// Clever, and allows any number of Optionals to be combined.
// OK, BUT COULD BE BETTER
Optional<BigDecimal> result =
Stream.of(first, second)
.filter(Optional::isPresent)
.map(Optional::get)
.reduce(BigDecimal::add);
// Even more clever!
// Exercise: verify this is correct.
Optional<BigDecimal> result =
first.map(b -> second.map(b::add).orElse(b)) // NOT RECOMMENDED
.map(Optional::of)
.orElse(second);
// Not the shortest, or cleverest, but is it the clearest ?
if (first.isEmpty() && second.isEmpty()) {
result = Optional.empty();
} else {
result = Optional.of(first.orElse(ZERO).add(second.orElse(ZERO)));
}
```
**Rule 6**: Avoid using Optional in fields, method parameters, and collections.
![[optional-rule6.png]]
![[optional-rule6-2.png]]
**Rule 7:** Avoid using identity-sensitive operations on Optionals.
![[optional-rule7.png]]
![[optional-rule7-2.png]]
***
**References**:
- [Optional by Stuart Marks](https://www.youtube.com/watch?v=fBYhtvY19xA&list=WL&index=100)
- [Java SE 8 Optional, a pragmatic approach](https://blog.joda.org/2015/08/java-se-8-optional-pragmatic-approach.html)
- [Java 8 SE Optional, a strict approach](https://nipafx.dev/stephen-colebourne-java-optional-strict-approach/)
- [Nothing is better than the Optional type](https://homes.cs.washington.edu/~mernst/advice/nothing-is-better-than-optional.html)
- [Optional Javadoc](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Optional.html)