Detailed explanation of the new feature of JDK1.8 Optional empty judgment, simplifying the operation of empty judgment

1. Introduction

A very interesting feature introduced from Java 8 is the Optional class. The main problem that the Optional class solves is the infamous NullPointerException - an exception that every Java programmer knows very well.
Essentially, this is a wrapper class that contains optional values, which means that the Optional class can either contain objects or be empty.
Optional is a powerful step towards functional programming in Java, and helps implement it in a paradigm. But the significance of Optional is obviously more than that.
Let's start with a simple use case. Prior to Java 8, any call to access an object method or property could result in a NullPointerException:

String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();

In this small example, if we need to ensure that no exceptions are raised, we have to explicitly check each value before accessing it:

if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        Country country = address.getCountry();
        if (country != null) {
            String isocode = country.getIsocode();
            if (isocode != null) {
                isocode = isocode.toUpperCase();
            }
        }
    }
}

This can easily become verbose and difficult to maintain. To simplify this process, let's look at how to do it with the Optional class. From creating and validating an instance, to using its different methods, and combining them with other methods that return the same type, here's a moment to witness the magic of Optional.

2. Advantages of using Optional

Optional is an object container with the following two characteristics:

  • Prompt the user to be aware that the object may be null
  • Simplify if else code

3. Optional use

1. Create:

Optional.empty(): Creates an empty Optional instance

//返回一个Null的optional
Optional<String> empty = Optional.empty();

Optional.of(T t): Create an Optional instance and throw an exception when t is null

//of 方法的值不能为空否则会抛出异常
Optional<String> optional1 = Optional.of("hello");

Optional.ofNullable(T t): Creates an Optional instance, but does not throw an exception when t is null, but returns an empty instance

//ofNullable 传入null不会异常
String str = null;
Optional<String> optional2 = Optional.ofNullable(str); 

2. Obtain:

get(): Get the object in the optional instance, and report an error when the optional container is empty

3. Judgment:

isPresent(): Determine whether the optional is empty, if it is empty, return false, otherwise return true

orElse(T other): If optional is not empty, return the object in optional; if it is null, return the default value of other

orElseGet(Supplier other): If optional is not empty, return the object in optional; if it is null, use the Supplier function to generate the default value other

orElseThrow(Supplier exception): If optional is not empty, return the object in optional; if it is null, throw the exception generated by the Supplier function

4. Filter:

filter(Predicate p): If the optional is not empty, execute the predicate function p, if the result of p is true, return the original optional, otherwise return the empty optional

5. Mapping:

map(Function<T, U> mapper): If optional is not empty, map the object t in optional to another object u, and store u in a new optional container.

flatMap(Function< T,Optional > mapper): As above, in the case that optional is not empty, map object t to another optional

Difference: map will automatically put u into optional, while flatMap needs to manually create an optional for u

4. Optional example

public class OptionalTest {
    public static void main(String[] arg) {
        //1.创建Optional对象,如果参数为空直接抛出异常
        Optional<String> str=Optional.of("a");

        //2.获取Optional中的数据,如果不存在,则抛出异常
        System.out.println(str.get());

        //3.optional中是否存在数据
        System.out.println(str.isPresent());

        //4.获取Optional中的值,如果值不存在,返回参数指定的值
        System.out.println(str.orElse("b"));

        //5.获取Optional中的值,如果值不存在,返回lambda表达式的结果
        System.out.println(str.orElseGet(()->new Date().toString()));

        //6.获取Optional中的值,如果值不存在,抛出指定的异常
        System.out.println(str.orElseThrow(()->new RuntimeException()));



        Optional<String> str2=Optional.ofNullable(null);

        //7.optional中是否存在数据
        System.out.println(str2.isPresent());

        //8.获取Optional中的值,如果值不存在,返回参数指定的值
        System.out.println(str2.orElse("b"));

        //9.获取Optional中的值,如果值不存在,返回lambda表达式的结果
        System.out.println(str2.orElseGet(()->new Date().toString()));

        //10.获取Optional中的值,如果值不存在,抛出指定的异常
        System.out.println(str2.orElseThrow(()->new RuntimeException()));
    }
}

output:

a
true
a
a
a
false
b
Mon May 15 20:22:47 CST 2022
Exception in thread “main” java.lang.RuntimeException
at OptionalTest.lambda$main 3 ( O p t i o n a l T e s t . j a v a : 42 ) a t O p t i o n a l T e s t 3(OptionalTest.java:42) at OptionalTest 3(OptionalTest.java:42)atOptionalTest$Lambda$4/931919113.get(Unknown Source)
at java.util.Optional.orElseThrow(Optional.java:290)
at OptionalTest.main(OptionalTest.java:42)

5. Optional example

package crazy;

import java.util.Optional;

class Company {
    private String name;
    private Optional<Office> office;

    public Company(String name, Optional<Office> office) {
        this.name = name;
        this.office = office;
    }

    public String getName() {
        return name;
    }

    public Optional<Office> getOffice() {
        return office;
    }
}

class Office {
    private String id;
    private Optional<Address> address;

    public Office(String id, Optional<Address> address) {
        this.id = id;
        this.address = address;
    }

    public String getId() {
        return id;
    }

    public Optional<Address> getAddress() {
        return address;
    }
}

class Address {
    private Optional<String> street;
    private Optional<String> city;

    public Address(Optional<String> street, Optional<String> city) {
        this.street = street;
        this.city = city;
    }

    public Optional<String> getStreet() {
        return street;
    }

    public Optional<String> getCity() {
        return city;
    }
}

public class OptionalDemo1 {

    public static void main(String[] args) {
        Optional<Address> address1 = Optional.of(new Address(Optional.ofNullable(null), Optional.of("New York")));
        Optional<Office> office1 = Optional.of(new Office("OF1", address1));
        Optional<Company> company1 = Optional.of(new Company("Door Never Closed", office1));

        // What is the street address of company1?
        // In which city company1 is located?
        Optional<Office> maybeOffice = company1.flatMap(Company::getOffice);
        Optional<Address> maybeAddress = office1.flatMap(Office::getAddress);
        Optional<String> maybeStreet = address1.flatMap(Address::getStreet);

        maybeStreet.ifPresent(System.out::println);
        if (maybeStreet.isPresent()) {
            System.out.println(maybeStreet.get());
        } else {
            System.out.println("Street not found.");
        }

        // shorter way
        String city = company1.flatMap(Company::getOffice)
                .flatMap(Office::getAddress)
                .flatMap(Address::getStreet)
                .orElse("City is not found.");

        System.out.println("City: " + city);

         // only print if city is not null
        company1.flatMap(Company::getOffice)
                .flatMap(Office::getAddress)
                .flatMap(Address::getCity)
                .ifPresent(System.out::println);

    }
}

This article is shared on the blog "Thinkingcao" (CSDN).
If there is any infringement, please contact [email protected] to delete it.
This article participates in the " OSC Yuanchuang Project ", you are welcome to join and share with us.

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324144826&siteId=291194637