Java 8 Goodies:
Optional
Removing Null Checks, Null Pointer Exceptions, (and Headaches)
The Null Pointer
How does one point to nothing?
The “Billion-Dollar mistake”
 Tony Hoare the creator of the null reference
 Created while designing ALGOL W
 Meant to model the absence of a value
 “… simply because it was so easy to implement”
 The cause of the dreaded Null Pointer Exceptions
NullPointerException
 Thrown when we attempt to use null value
 The most thrown exception
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; }
}
public String getCarInsuranceName(Person person) {
return person.getCar().getInsurance().getName();
}
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”;
}
Attempt 1: Deep Doubts
public String getCarInsuranceName(Person person) {
if (person == null) {
return “Unknown”;
}
Car car = person.getCar();
if (car == null) {
return “Unknown”;
}
Insurance insurance = car.getInsurance();
if(insurance == null) {
return “Unknown”;
}
return insurance.getName();
}
Attempt 2: Multiple Exits
So what’s wrong with null?
 It’s a source of error
 NullPointerException
 It bloats code
 Worsens readability
 It meaningless
 Has no semantic meaning
 It breaks Java’s philosophy
 Java hides pointers from developers, except in one case
So what can we do about it?
Introducing…
Optional
 New class located at java.util.Optional<T>
 Encapsulates optional values
 It wraps the value if it’s there, and is empty if it isn’t
 Optional.empty()
 Signals that a missing value is acceptable
 We can’t deference null, but we can dereference Optional.empty()
Car
Optional<Car> Optional<Car>
public class Person {
private Optional<Car> car;
public Optional<Car> getCar() { return car; }
}
public class Car {
private Optional<Insurance> insurance;
public Optional<Insurance> getInsurance() { return insurance; }
}
public class Insurance {
private String name;
public String getName() { return name; }
}
Progressive Refactored
Warning before we progress!
 Optionals are not intended to replace all null references
 Design more comprehensible APIs
 Forces caller to deal with the absence of a value
Patterns for Optionals
How do we make them?
How do we use them?
What can we do with them?
Creating Optional objects
 Empty Optional
 Optional<T> opt = Optional.empty();
 Optional<Car> optCar = Optional.empty();
 Optional from a non-null value
 Optional<T> opt = Optional.of(T value);
 Optional<Car> optCar = Optional.of(car);
 Optional from a null value
 Optional<T> opt = Optional.ofNullable(T value);
 Optional<Car> optCar = Optional.ofNullable(car);
How do we use Optional?
Optional<Car> optCar = Optional.ofNullable(car);
Car realCar = optCar.get(); DO NOT DO THIS! (ANTI-PATTERN)
 Throws a NoSuchElementException if empty
 Same conundrum as using null
Quick commercial break
Functional Programming in Java 8
Filtering (Extracts)
// Get the unique even number from a list
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 == 0) // get even number
.distinct()
.forEach(System.out::println); // 2, 4
Stream<T> filter(Predicate<? super T> predicate)
Returns a stream consisting of the elements of this stream that match the given
predicate.
Mapping (Transforms)
// Get the length of the each word in a list
List<String> words = Arrays.asList("Hello", "World");
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(toList());
System.out.println(wordLengths); // [5, 5]
<R> Stream<R> map(Function<? super T,? extends R> mapper)
Returns a stream consisting of the results of applying the given function to the
elements of this stream.
Back to our scheduled programming
(no pun intended)
The best ways to use Optional
Optional<Insurance> optInsurance = Optional.ofNullable(insurance)
Optional<String> name = optInsurance.map(Insurance::getName)
Extracting and Transforming Values
String name = null;
if(insurance != null){
name = insurance.getName()
}
public class Insurance {
private String name;
public String getName() { return name; }
}
Get the name of an insurance policy that may not be there.
Chaining Optionals
Optional<Person> optPerson = Optional.ofNullable(person)
Optional<String> name = optPerson.map(Person::getCar)
.map(Car::getInsurance)
.map(Insurance::getName);
public String getCarInsuranceName(Person person) {
return person.getCar().getInsurance().getName();
}
Get the name of an insurance policy that a person may have.
• Doesn’t compile
• getCar returns Optional<Car>
• Results in Optional<Optional<Car>>
FlatMapping
Optional<Person> optPerson = Optional.ofNullable(person)
Optional<String> name = optPerson.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName);
public String getCarInsuranceName(Person person) {
return person.getCar().getInsurance().getName();
}
Get the name of an insurance policy that a person may have.
• flatMap flattens multi-level operations into a single operation
• flatMap performs on the value inside of the Optionals
Bit of Refactoring
Public String getCarInsuranceName(Optional<Person> person) {
return person.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
// default value if Optional is empty
.orElse(“Unknown”);
}
public String getCarInsuranceName(Person person) {
return person.getCar().getInsurance().getName();
}
Get the name of an insurance policy that a person may have.
Filtering with Optionals
Insurance insurance = new Insurance(“Progressive”);
Optional<Insurance> optInsurance = Optional.of(insurance);
optionalInsurance.filter(i -> “Progressive”.equals(insurance.getName()))
// Print the name if it exsists.
.ifPresent(x -> System.out.println(“ok”));
Insurance insurance = new Insurance(“Progressive”);
If (insurance != null && “Progressive”.equals(insurance.getName())){
System.out.println(“ok”);
}
Check to see if an insurance name is equal to “Cambridge”
Combining Maps and Filters
Public String getCarInsuranceName(Optional<Person> person, int minAge) {
return person.filter(age -> p.getAge() >= minAge)
.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
// default value if Optional is empty
.orElse(“Unknown”);
}
Get the name of an insurance policy that a person may have, only if the person’s
age is greater than a certain number.
More Practical Examples
Some common use cases of Optional
Wrapping Potentially Null Values
Map<String, Object> map = new HashMap<>();
// Potentially returns a null value
Object value = map.get(“key”);
// Safely transforms a potential null into an Optional
Optional<Object> value = Optional.ofNullable(map.get(“key”));
• Existing APIs mostly return null for absent values
• We’d prefer if they returned an Optional
• Can’t change them, but we wrap them
Throwing Exceptions
Public String getCarInsuranceName(Optional<Person> person, int minAge) {
return person.filter(age -> p.getAge() >= minAge)
.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
// Throw an appropriate exception
.orElseThrow(IllegalStateException::new);
}
Sometimes you need to throw an exception if a value is absent.
Optional Methods
Method: Description:
empty Returns an empty Optional instance
filter Returns the Optional value if it matches the predicate;
otherwise returns an empty Optional
flatMap If a value is present, it returns the Optional resulting
from the application of the provided mapping function;
otherwise returns an empty Optional
get Returns the wrapped value if present; throws an
exception if not
ifPresent If the value is present, it invokes the Consumer;
otherwise does nothing
isPresent Returns true if there’s a value
Optional Methods
Method: Description:
map If a value is present, applies the mapping function
of Returns an Optional that wraps the value if it’s not null
ofNullable Returns an Optional that wraps the value if it’s not null;
Returns an empty Optional if it is null
orElse Returns the value if present; otherwise does the default
given
orElseGet Returns the value if present; otherwise invokes the
Supplier
orElseThrow Returns the value if present; otherwise throws the
exception
Summary
 Null references have been historically introduced to signal absences
 Optional has been introduced to model presence or absence
 Can create Optional objects using factory methods:
 Optional.empty
 Optional.of
 Optional.ofNullable
 Optional supports methods suited for functional programming
 Using Optional forces callers to actively deal with potential absences
 Optional can help you design better APIs

Optional in Java 8

  • 1.
    Java 8 Goodies: Optional RemovingNull Checks, Null Pointer Exceptions, (and Headaches)
  • 2.
    The Null Pointer Howdoes one point to nothing?
  • 3.
    The “Billion-Dollar mistake” Tony Hoare the creator of the null reference  Created while designing ALGOL W  Meant to model the absence of a value  “… simply because it was so easy to implement”  The cause of the dreaded Null Pointer Exceptions
  • 4.
    NullPointerException  Thrown whenwe attempt to use null value  The most thrown exception
  • 5.
    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; } } public String getCarInsuranceName(Person person) { return person.getCar().getInsurance().getName(); }
  • 6.
    public String getCarInsuranceName(Personperson) { if (person != null) { Car car = person.getCar(); if (car != null) { Insurance insurance = car.getInsurance(); if(insurance != null) { return insurance.getName(); } } } return “Unknown”; } Attempt 1: Deep Doubts
  • 7.
    public String getCarInsuranceName(Personperson) { if (person == null) { return “Unknown”; } Car car = person.getCar(); if (car == null) { return “Unknown”; } Insurance insurance = car.getInsurance(); if(insurance == null) { return “Unknown”; } return insurance.getName(); } Attempt 2: Multiple Exits
  • 8.
    So what’s wrongwith null?  It’s a source of error  NullPointerException  It bloats code  Worsens readability  It meaningless  Has no semantic meaning  It breaks Java’s philosophy  Java hides pointers from developers, except in one case
  • 9.
    So what canwe do about it? Introducing…
  • 10.
    Optional  New classlocated at java.util.Optional<T>  Encapsulates optional values  It wraps the value if it’s there, and is empty if it isn’t  Optional.empty()  Signals that a missing value is acceptable  We can’t deference null, but we can dereference Optional.empty() Car Optional<Car> Optional<Car>
  • 11.
    public class Person{ private Optional<Car> car; public Optional<Car> getCar() { return car; } } public class Car { private Optional<Insurance> insurance; public Optional<Insurance> getInsurance() { return insurance; } } public class Insurance { private String name; public String getName() { return name; } } Progressive Refactored
  • 12.
    Warning before weprogress!  Optionals are not intended to replace all null references  Design more comprehensible APIs  Forces caller to deal with the absence of a value
  • 13.
    Patterns for Optionals Howdo we make them? How do we use them? What can we do with them?
  • 14.
    Creating Optional objects Empty Optional  Optional<T> opt = Optional.empty();  Optional<Car> optCar = Optional.empty();  Optional from a non-null value  Optional<T> opt = Optional.of(T value);  Optional<Car> optCar = Optional.of(car);  Optional from a null value  Optional<T> opt = Optional.ofNullable(T value);  Optional<Car> optCar = Optional.ofNullable(car);
  • 15.
    How do weuse Optional? Optional<Car> optCar = Optional.ofNullable(car); Car realCar = optCar.get(); DO NOT DO THIS! (ANTI-PATTERN)  Throws a NoSuchElementException if empty  Same conundrum as using null
  • 16.
    Quick commercial break FunctionalProgramming in Java 8
  • 17.
    Filtering (Extracts) // Getthe unique even number from a list List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); numbers.stream() .filter(i -> i % 2 == 0) // get even number .distinct() .forEach(System.out::println); // 2, 4 Stream<T> filter(Predicate<? super T> predicate) Returns a stream consisting of the elements of this stream that match the given predicate.
  • 18.
    Mapping (Transforms) // Getthe length of the each word in a list List<String> words = Arrays.asList("Hello", "World"); List<Integer> wordLengths = words.stream() .map(String::length) .collect(toList()); System.out.println(wordLengths); // [5, 5] <R> Stream<R> map(Function<? super T,? extends R> mapper) Returns a stream consisting of the results of applying the given function to the elements of this stream.
  • 19.
    Back to ourscheduled programming (no pun intended) The best ways to use Optional
  • 20.
    Optional<Insurance> optInsurance =Optional.ofNullable(insurance) Optional<String> name = optInsurance.map(Insurance::getName) Extracting and Transforming Values String name = null; if(insurance != null){ name = insurance.getName() } public class Insurance { private String name; public String getName() { return name; } } Get the name of an insurance policy that may not be there.
  • 21.
    Chaining Optionals Optional<Person> optPerson= Optional.ofNullable(person) Optional<String> name = optPerson.map(Person::getCar) .map(Car::getInsurance) .map(Insurance::getName); public String getCarInsuranceName(Person person) { return person.getCar().getInsurance().getName(); } Get the name of an insurance policy that a person may have. • Doesn’t compile • getCar returns Optional<Car> • Results in Optional<Optional<Car>>
  • 22.
    FlatMapping Optional<Person> optPerson =Optional.ofNullable(person) Optional<String> name = optPerson.flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName); public String getCarInsuranceName(Person person) { return person.getCar().getInsurance().getName(); } Get the name of an insurance policy that a person may have. • flatMap flattens multi-level operations into a single operation • flatMap performs on the value inside of the Optionals
  • 23.
    Bit of Refactoring PublicString getCarInsuranceName(Optional<Person> person) { return person.flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) // default value if Optional is empty .orElse(“Unknown”); } public String getCarInsuranceName(Person person) { return person.getCar().getInsurance().getName(); } Get the name of an insurance policy that a person may have.
  • 24.
    Filtering with Optionals Insuranceinsurance = new Insurance(“Progressive”); Optional<Insurance> optInsurance = Optional.of(insurance); optionalInsurance.filter(i -> “Progressive”.equals(insurance.getName())) // Print the name if it exsists. .ifPresent(x -> System.out.println(“ok”)); Insurance insurance = new Insurance(“Progressive”); If (insurance != null && “Progressive”.equals(insurance.getName())){ System.out.println(“ok”); } Check to see if an insurance name is equal to “Cambridge”
  • 25.
    Combining Maps andFilters Public String getCarInsuranceName(Optional<Person> person, int minAge) { return person.filter(age -> p.getAge() >= minAge) .flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) // default value if Optional is empty .orElse(“Unknown”); } Get the name of an insurance policy that a person may have, only if the person’s age is greater than a certain number.
  • 26.
    More Practical Examples Somecommon use cases of Optional
  • 27.
    Wrapping Potentially NullValues Map<String, Object> map = new HashMap<>(); // Potentially returns a null value Object value = map.get(“key”); // Safely transforms a potential null into an Optional Optional<Object> value = Optional.ofNullable(map.get(“key”)); • Existing APIs mostly return null for absent values • We’d prefer if they returned an Optional • Can’t change them, but we wrap them
  • 28.
    Throwing Exceptions Public StringgetCarInsuranceName(Optional<Person> person, int minAge) { return person.filter(age -> p.getAge() >= minAge) .flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) // Throw an appropriate exception .orElseThrow(IllegalStateException::new); } Sometimes you need to throw an exception if a value is absent.
  • 29.
    Optional Methods Method: Description: emptyReturns an empty Optional instance filter Returns the Optional value if it matches the predicate; otherwise returns an empty Optional flatMap If a value is present, it returns the Optional resulting from the application of the provided mapping function; otherwise returns an empty Optional get Returns the wrapped value if present; throws an exception if not ifPresent If the value is present, it invokes the Consumer; otherwise does nothing isPresent Returns true if there’s a value
  • 30.
    Optional Methods Method: Description: mapIf a value is present, applies the mapping function of Returns an Optional that wraps the value if it’s not null ofNullable Returns an Optional that wraps the value if it’s not null; Returns an empty Optional if it is null orElse Returns the value if present; otherwise does the default given orElseGet Returns the value if present; otherwise invokes the Supplier orElseThrow Returns the value if present; otherwise throws the exception
  • 31.
    Summary  Null referenceshave been historically introduced to signal absences  Optional has been introduced to model presence or absence  Can create Optional objects using factory methods:  Optional.empty  Optional.of  Optional.ofNullable  Optional supports methods suited for functional programming  Using Optional forces callers to actively deal with potential absences  Optional can help you design better APIs