Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Optional<Java>

074c1726aee7c73df923c3d5064ab861?s=47 Pedro Tavares
September 20, 2017

 Optional<Java>

A wise man once said you are not a real Java programmer until you've dealt with a null pointer exception. Joking aside, the null reference is the source of many problems because it is often used to denote the absence of a value. Java SE 8 introduces a new class called java.util.Optional that can alleviate some of these problems.

074c1726aee7c73df923c3d5064ab861?s=128

Pedro Tavares

September 20, 2017
Tweet

Transcript

  1. Optional<Java> Say no to NullPointerExceptions! @ordepdev

  2. The billion dollar mistake Null references have historically been a

    bad idea
  3. Problems with null It’s meaningless. It bloats your code. It’s

    a source of error. It breaks Java philosophy. It creates a hole in the type system.
  4. Before Optional<T> public class Person { private Car car; public

    Car getCar() { return car; } public class Car { private Insurance insurance; public Insurance getInsurance() { return insurance; } } public class Insurance { private String name; public String getName() { return name; } } }
  5. Before Optional<T> public String getCarInsuranceName(Person person) { if (person !=

    null) { Car car = person.getCar(); if (car != null) { Insurance insurance = car.getInsurance(); if (insurance != null) { return insurance.getName(); } } } return "Unknown"; }
  6. Better alternative? person?.car?.insurance?.name Safe navigation operator from languages like Groovy,

    C#, and Kotlin Maybe a = Nothing | Just a Types that encapsulates an optional value from languages like Haskell and Scala Option[A] = if (x == null) None else Some(x)
  7. Optional<T> T Optional<T> Optional<T> Is empty Contains a non-null reference

    to a given T
  8. IT’S A MONAD! filter(), map(), flatMap(), orElse()

  9. WELL… ALMOST! Optional<Car> car = null;

  10. FROM NULL TO Optional<T> public class Person { private Car

    car; public Optional<Car> getCar() { return Optional.ofNullable(car); } public class Car { private Insurance insurance; public Optional<Insurance> getInsurance() { return Optional.ofNullable(insurance); } } public class Insurance { private String name; public String getName() { return name; } } }
  11. FROM NULL TO Optional<T> public String getCarInsuranceName(Person person) { return

    Optional.ofNullable(person) .flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown"); }
  12. FROM NULL TO Optional<T> public String getCarInsuranceName(Person person) { return

    Optional.ofNullable(person) .flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown"); }
  13. FROM NULL TO Optional<T> public String getCarInsuranceName(Person person) { return

    Optional.ofNullable(person) .flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown"); }
  14. FROM NULL TO Optional<T> public String getCarInsuranceName(Person person) { return

    Optional.ofNullable(person) .flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown"); }
  15. FROM NULL TO Optional<T> public String getCarInsuranceName(Person person) { return

    Optional.ofNullable(person) .flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown"); }
  16. OR EVEN IF IT’S REQUIRED… public String getCarInsuranceName(Person person) {

    return Optional.ofNullable(person) .flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElseThrow(() -> new RuntimeException( “Insurance not available.” ); }
  17. CODE SMELLS Don’t try this at home

  18. METHOD CHAINING IS COOL, BUT… AVOIDING IF-STATEMENTS Optional.ofNullable(person) .ifPresent(this::doSomeWork); if

    (person != null) { this.doSomeWork(); } just stay with…
  19. Optional as preconditions Optional.ofNullable(person) .ifPresent(IllegalArgumentException::new); Preconditions.checkNotNull(person); just stay with…

  20. NESTED OPTIONALS Optional<BigDecimal> result = first.map(b -> second.map(b::add).orElse(b)) .map(Optional::of) .orElse(second);

    if(!first.isPresent() && !second.isPresent()) { return Optional.empty(); } return Optional.of( first.orElse(ZERO).add(second.orElse(ZERO))); just stay with…
  21. OPTIONALS IN FIELDS AND PARAMS private final Optional<Car> car; public

    Optional<Car> car() { return this.car; } private final @Nullable Car car; public Optional<Car> car() { return Optional.ofNullable(this.car); } just stay with…
  22. be lazy all the time public Person findOrCreate(PersonRequest request) {

    return repo.find(request.id()) .orElse(this.create(request)); } public Person findOrCreate(PersonRequest request) { return repo.find(request.id()) .orElseGet(() -> this.create(request)); } just stay with…
  23. Optional.get() NoSuchElementException “Biggest Java 8 regret”

  24. Key rules #1 Never use null for an Optional variable

    or return value; #2 Never use Optional.get(); #3 Don't use Optional just for chaining methods; #4 Don’t replace every single null reference with Optional; #5 Avoid using Optional in fields, parameters and collections;
  25. Thank you. @ordepdev