+ - 0:00:00
Notes for current slide
Notes for next slide

The curse of Optional


  • What is Java's Optional?
  • When to use it
  • How to use it
  • Anti-patterns
1 / 8

Java's Optional


  • Java's Optional made it to prime-time in Java 1.8
  • It is a container object which may or may not contain a non-null value
  • Other languages have a similar concept
  • This is a value-based class
  • Has some helper methods to look inside the container
    • isPresent() - returns if the value inside is not null
    • get() - returns the non-null value
  • Some more helper methods for fluid coding and method chaining
    • orElse(T other) - get the value or other when value is missing
    • orElseGet(Supplier<? extends T> other)
    • orElseThrow(Supplier<? extends X> exceptionSupplier)
    • map(Function<? super T,? extends U> mapper)
    • ifPresent(Consumer<? super T> consumer)
2 / 8

Java's Design Decisions around Optional


  • A variable can represent two states simultaneously: has a value or empty
  • null is the source of evil: throws NullPointerException when not handled
  • Optional actually says that this variable may or may not contain a value
  • null values can mean several things:
    • This is default value for object types?
    • This is an expected value (see Map.get())?
    • This is a valid value for a variable?
    • The method returning this value doesn't behave properly?
    • Imagine trying to answer these questions when debugging a NPE
  • Optional types force the consumer to handle both cases: when there's a value and when the value is missing. There's no excuse for not doing so
3 / 8

Why Java's Optional


  • Usually, to handle null values in Java, one would do
public static boolean isExpectedValue(String other) {
// I don't care about the value of `other`, it will never throw a NPE
return EXPECTED_VALUE.equals(other);
}
@ParameterizedTest(name = "Should return {1} when value is \"{0}\"")
@CsvSource({",'false'","'','false'","'boo','false'","'blah','true'"})
void shouldMatchExpectedValue(String otherValue, boolean expected) {
assertThat(App.isExpectedValue(otherValue)).isEqualTo(expected);
}
// will output: 'Should return false when value is "null"'
  • Primitive types cannot be null
  • Methods returning object types should always return an instance or null
  • We need to check if the returned instance is null or not
  • We cannot chain methods with null checks and have fluent code
  • Basically allows writing code without the loved hated null check
4 / 8

When to use Optional


  • To return an object that might contain a value or not
@Override
public Room execute(final Room request) {
return RoomEntityToRoom.map(roomsRepository.save(RoomToRoomEntity.map(request)));
}
  • To allow the caller of that function to continue a series of fluent calls
@PostMapping
@ResponseBody
public ResponseEntity<RoomResponse> createRoom(@Validated RoomRequest request) {
return Optional.ofNullable(request)
.map(RoomRequestToRoom::map)
.map(createRoomUseCase::execute)
.map(RoomToRoomResponse::map)
.map(response -> new ResponseEntity<>(response, HttpStatus.CREATED))
.orElseGet(() -> new ResponseEntity<>(HttpStatus.BAD_REQUEST));
}
5 / 8

Another usage example


public static String mayNotReturnAString() {
final Random random = new Random();
return random.nextInt() % 2 == 0 ? "Blah" : null;
}
public static Optional<String> maybeString() {
final Random random = new Random();
return random.nextInt() % 2 == 1 ? Optional.of("Boo") : Optional.empty();
}
public static void handleStrings() {
String needsNullCheck = mayNotReturnAString();
if (null != needsNullCheck)) {
System.out.printf("No Optional value is not null: %s%n", needsNullCheck);
} else {
System.out.println("No Optional value is null");
}
maybeString().ifPresentOrElse(
s -> System.out.printf("Optional value is not null: %s%n", s),
() -> System.out.println("Optional value is null"));
}
  • Which usage is cleaner?
6 / 8

When not to use Optional

Method overloading


  • When a parameter might be missing from a method: use method overloading
7 / 8

When not to use Optional

When creating many objects in a short amount of time


8 / 8

Java's Optional


  • Java's Optional made it to prime-time in Java 1.8
  • It is a container object which may or may not contain a non-null value
  • Other languages have a similar concept
  • This is a value-based class
  • Has some helper methods to look inside the container
    • isPresent() - returns if the value inside is not null
    • get() - returns the non-null value
  • Some more helper methods for fluid coding and method chaining
    • orElse(T other) - get the value or other when value is missing
    • orElseGet(Supplier<? extends T> other)
    • orElseThrow(Supplier<? extends X> exceptionSupplier)
    • map(Function<? super T,? extends U> mapper)
    • ifPresent(Consumer<? super T> consumer)
2 / 8
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow