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

Optional<Java>

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.

Pedro Tavares

September 20, 2017
Tweet

More Decks by Pedro Tavares

Other Decks in Programming

Transcript

  1. 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.
  2. 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; } } }
  3. 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"; }
  4. 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)
  5. 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; } } }
  6. 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"); }
  7. 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"); }
  8. 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"); }
  9. 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"); }
  10. 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"); }
  11. 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.” ); }
  12. 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…
  13. 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…
  14. 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…
  15. 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;