Q.What is the alternative to null in Java?
Java 8 introduces a new class called java.util.Optional<T> that’s inspired by the ideas of Haskell and Scala. It’s a class that encapsulates an optional value.
Q.How do you model the absence of a value?
Imagine you have the following nested object structure for a person owning a car and having car insurance.
The Person / Car / Insurance data model
If you design your classes like below
I argue that using null to represent the absence of a value is the wrong approach.
What you need is a better way to model the absence and presence of a value.
Redefining the Person / Car / Insurance data model using Optional
Creating Optional objects
There are several ways to create Optional objects.
Empty optional:
Optional<Car> optCar = Optional.empty();
Optional from a non-null value:
Optional<Car> optCar = Optional.of(car);
If car were null, a NullPointerException would be immediately thrown (rather than getting a
latent error once you try to access properties of the car).
Optional from null:
Optional<Car> optCar = Optional.ofNullable(car);
If car were null, the resulting Optional object would be empty
The methods of the Optional class
Java 8 introduces a new class called java.util.Optional<T> that’s inspired by the ideas of Haskell and Scala. It’s a class that encapsulates an optional value.
Q.How do you model the absence of a value?
Imagine you have the following nested object structure for a person owning a car and having car insurance.
The Person / Car / Insurance data model
If you design your classes like below
- class Person{
- private Car car;
- public Car getCar() {
- return car;
- }
- }
- class Car{
- private Insurance insurance;
- public Insurance getInsurance() {
- return insurance;
- }
- }
- class Insurance {
- private String name;
- public String getName() {
- return name;
- }
- }
- class Test {
- public String getCarInsuranceName(Person person) {
- return person.getCar().getInsurance().getName();
- }
- public static void main(String[] args) {
- Test t = new Test();
- t.getCarInsuranceName(new Person());
- }
- It’s a source of error. NullPointerException is by far the most common exception in Java.
- It bloats your code. It worsens readability by making it necessary to fill your code with often deeply nested null checks.
- It’s meaningless. It doesn’t have any semantic meaning, and in particular, it represents the wrong way to model the absence of a value in a statically typed language.
- It breaks Java philosophy. Java always hides pointers from developers except in one case: the null pointer.
- It creates a hole in the type system. null carries no type or other information, meaning it can be assigned to any reference type. This is a problem because, when it’s propagated to another part of the system, you have no idea what that null was initially supposed to be.
I argue that using null to represent the absence of a value is the wrong approach.
What you need is a better way to model the absence and presence of a value.
Redefining the Person / Car / Insurance data model using Optional
- class Person {
- private Optional<Car> car;
- public Optional<Car> getCar() {
- return car;
- }
- }
- class Car {
- private Optional<Insurance> insurance;
- public Optional<Insurance> getInsurance() {
- return insurance;
- }
- }
- class Insurance {
- private String name;
- public String getName() {
- return name;
- }
- }
- class OptionalVersion {
- public String getCarInsurance(Optional<Person1> person) {
- return person.flatMap(Person1::getCar).flatMap(Car::getInsurance).map(Insurance::getName).orElse("Unknow");
- }
- public static void main(String[] args) {
- OptionalVersion t = new OptionalVersion();
- Optional<Person> p = Optional.empty();
- System.out.println(t.getCarInsurance(p));;
- }
- }
Creating Optional objects
There are several ways to create Optional objects.
Empty optional:
Optional<Car> optCar = Optional.empty();
Optional from a non-null value:
Optional<Car> optCar = Optional.of(car);
If car were null, a NullPointerException would be immediately thrown (rather than getting a
latent error once you try to access properties of the car).
Optional from null:
Optional<Car> optCar = Optional.ofNullable(car);
If car were null, the resulting Optional object would be empty
The methods of the Optional class
Method | Description |
empty | Returns an empty Optional instance |
filter | If the value is present and matches the given predicate,
returns this Optional; otherwise returns the empty one |
flatMap | If a value is present, returns the Optional resulting from the
application of the provided mapping function to it; otherwise returns the empty Optional |
get | Returns the value wrapped by this Optional if present, otherwise throws a NoSuchElementException |
ifPresent | If a value is present, invokes the specified consumer with the value; otherwise does nothing |
isPresent | Returns true if there is a value present; otherwise false |
map | If a value is present, applies the provided mapping function to it |
of | Returns an Optional wrapping the given value or throws a
NullPointerException if this value is null |
ofNullable | Returns an Optional wrapping the given value or the empty Optional if this value is null |
orElse | Returns the value if present or the given default value otherwise |
orElseGet | Returns the value if present or the one provided by the given Supplier otherwise |
orElseThrow | Returns the value if present or throws the exception created by the given Supplier otherwise |