preface

After sorting out the JAVA8 feature “Stream”, today we will introduce another feature “Optional”. The Optional API provides enough methods for developers to handle NULL situations in a more secure manner. Before JAVA8, a function was supposed to return a non-empty object but occasionally returned null. In JAVA8, it was not recommended that you return null but Optional.

The body of the

The sample

In traditional writing, when we get an object from another function, we don’t know if the object is a null object. We usually use an if logic statement to determine whether the object is a null object to avoid runtime exceptions.

static Random random = new Random();

public static void main(String[] args) {
    String value = getValue();
    if (value == null)
        value = "NO VALUE";
    elsevalue = value.. toUpperCase(); System.out.println(value); }static String getValue(a) {
    return getRandomBoolean() ? null : "VERY GOOD";
}

static boolean getRandomBoolean(a) {
    //0 is true and 1 is false
    return random.nextInt(2) = =0;
}
Copy the code

When we refactor getValue() from String to Optional

, the code becomes a chain structure. It not only reduces the previous complexity, but also improves readability.

public static void main(String[] args) {
    String value = getValue().map(String::toUpperCase)
            .orElse("NO VALUE");
    System.out.println(value);
}

static Optional<String> getValue(a) {
    return getRandomBoolean() ? Optional.empty() : Optional.of("VERY GOOD");
}
Copy the code

Other common usage examples

IfPresent If a value exists, call the specified Consumer with the value. Otherwise, no action is taken. Again quoting the code above, this will print “VERY GOOD” or not:

@Test
public void TestExample2_1(a) {
    Optional<String> name = getValue();
    name.ifPresent(x -> {
        System.out.println(x);
    });
}
Copy the code

OrElseGet orElseGet is roughly similar to the orElse method used above. The difference is the default value you get. The orElse method takes the string passed as the default value, and the orElseGet method can accept the Supplier interface implementation to generate the default value:

@Test
public void TestExample2_2(a) {
    String value = getValue().map(String::toUpperCase)
            .orElseGet(()->"NO VALUE");
    System.out.println(value);
}
Copy the code

Result -> option. of(result). The result of flatMap must be of the Optional type. Optional -> Optional:

@Test
public void TestExample2_3(a) {
    Optional<Flight> flight = Optional.of(new Flight());
    String value = flight.flatMap(Flight::getDeparture)
            .map(Location::getName)
            .get();
    System.out.println(value);
}

class Flight {
    private Location departure;
    
    // Return Optional to look at flatMap
    public Optional<Location> getDeparture(a) { 
        returnOptional.of(departure); }}class Location {

    private String name;
    
    // The value is returned as String
    public String getName(a) {
        returnname; }}Copy the code

Filter Returns the Optional that describes the value if it exists and is filtered by the given criteria, otherwise returns an empty Optional.

@Test
public void TestExample2_4(a) {
    Optional<Flight> flight = Optional.of(new Flight());
    String value = flight.flatMap(Flight::getDeparture)
            .map(Location::getName)
            .filter(item->"Good".equals(item))
            .get();
    System.out.println(value);
}
Copy the code

conclusion

Optional provides a number of methods for developers to handle null situations more smoothly, and the Optional API allows us to call them either functionally or through lambda statements. This code looks cleaner and more readable. But by wrapping raw values into Optional instances, performance in tight loops is questionable.

Write good welcome correction, feel sorted out of a good point of praise 😂.