SoFunction
Updated on 2025-03-03

Detailed explanation of the usage of Optional class in Java

Preface

The method of calling an empty reference in Java to attempt to access the attribute of the null reference is to report a NullPointerException exception. In actual projects, a large number of empty values ​​will be processed, and the code will have many conditional judgments, which are difficult to read and maintain.

        if(user!=null){
            (());
        }else {
            User defaultUser = new User("Stark", "Tony Stark");
            (());
        }

1. What is Optional?

The Optional class introduces an explicit way to handle objects that may be empty, forcing programmers to explicitly handle when they may be empty to avoid null pointer exceptions.

Optional is similar to a container, which can contain various types of values ​​or be null. The Optional class provides a series of methods to easily manipulate internal values. Commonly used methods include get, orElse, orElseGet, orElseThrow, etc.

Optional's design also takes into account the principle of functional programming. It can be used in combination with features such as Lambda expressions and StreamAPI. Chain calls can be performed instead of imperative programming. null values ​​can be checked by writing if conditional statements.

2. Methods of Optional object

First we need to create two classes, User class and UserRepository class.

User class

import ;

public class User {
    String name;
    String fullName;

    public User(String name, String fullName) {
         = name;
         = fullName;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
         = name;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
         = fullName;
    }
}

UserRepository class

import ;

public class UserRepository {
    public User findUserByName(String name){
        if(("Peter")){
            return new User("Peter","Peter Parker");
        }
        else {
            return null;
        }
    }
}

, isEmpty method

The isPresent method is used to check whether there is a value in optional, and returns a Boolean value, exists as true, and does not exist as false.

The isEmpty method is used to check whether the optional is empty, returns a boolean value, is empty and true, and is not empty and false.

		//Create an Optional object with a value of null		Optional<Object> optionalBox = ();
		(());
		(());

The return value is false and true.

, of, ofNullable methods

If the created object is null, the empty() method can be used.

		Optional<Object> optionalBox = ();

To create an object that is not null, you need to call the of method. If the value is null, a NullPointerException exception is thrown.

        String value = "Peter";
        Optional<String> optionalBox = (value);

If you want to create an object that may be null, you can use the ofNullable() method.

        String value = "Peter";
        Optional<String> optionalBox = (value);

, orElse, orElseGet and orElseThrow methods

You can use the get() method to get the value. If the value object is null, an exception will be reported (not an exception).

        String value2 = ();
        (value2);

Here we modify the findUserByName method in the UserRepository class to make its return value an Optional object.

    public Optional<User> findUserByName(String name){
        if(("Peter")){
            return (new User("Peter","Peter Parker"));
        }
        else {
            return ();
        }
    }

orElse is an important method in the Optional class, which is used to get a value or provide a default value if the value is empty.

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = ("Peter2");
        User user = (new User("Stark","Tony Stark"));
        (());

The orElse method will create a new User object even if the data read is not null. Therefore, it is best to use the orElseGet method that will only create a new object when the read data is null.
The parameters of the orElseGet method are Supplier's functional interface and need to be implemented using Lambda expressions.

        (()->new User("Stark","Tony Stark"));
        (());

The orElseThrow method is used to throw a specified exception when the value in the Optional object is empty.
The orElseThrow method can generate custom exceptions through Supplier's functional interface, and the default exception is thrown.

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = ("Peter2");
        (()->new RuntimeException("User not found"));

, ifPresentOrElse, filter method

If the object in the ifPresent method parameter is not null, the method in Labmda will be executed;

If the parameter object is null, the method in Labmda will not be executed and there will be no errors.

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = ("Peter2");
        (user -> (()));

When we want the value to be empty, we need to use the ifPresentOrElse method.

        (user -> (()),
                ()->("User not found"));

If the conditions in the filter method are met, an Optional object containing the value will be returned. If it is not met, an empty Optional object will be returned.

        Optional<User> optionalUser2 = (user -> ().equals("Peter Parker"));
        (());

with flatMap method

Before performing two methods, you need to modify the return value of the getFullName method in the User class to Optional.

    public Optional<String> getFullName(){
        return (fullName);
    }

map method: convert the value in Optional (if the value is empty, the map method will do nothing and will directly return the empty Optional object).
This transformation is based on the function that provides the map, and this transformation is optional. If the optional value is empty, no changes will be made, and the map method will not change the original Optional object, but will return a new Optional object. Therefore, multiple conversion operations can be called chained.

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = ("Peter");
        Optional<String> optionalFullName = (User::getFullName);
        (());

The flatmap method is used to flatten nested Optional structures to avoid introducing unnecessary nesting levels. The conversion function of flatmap must return another Optional object, meaning that the flatMap method can be used for nested Optional cases, and two Optional objects that are nested relationships can be converted into one. If the original Optional object is empty, or the Optional object returned by the conversion function is empty, then the final result is also an empty Optional object.

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = ("Peter");
        Optional<String> optional = (User::getFullName);

If you only need to convert the values ​​in the Optional object without nested Optional, then using the map method is more appropriate.
If you want to do some operations and return another Optional object, the flatmap method is more suitable.

method

Optional's stream method can convert Optional objects into Stream objects and perform streaming operations on the values. If the Optional object contains a value, encapsulate this value into a Stream stream. If the Optional object is empty, create an empty Stream stream.

        UserRepository userRepository = new UserRepository();
        Optional<User> optionalUser = ("Peter");
        Stream<String> a =(User::getName).stream();
        (::println);

3. Not suitable for use of Optional objects

It should not be used for fields of classes, which increase memory consumption and complicate serialization;

It should not be used for method parameters, complicating the understanding and use of methods;

It is not applied to constructor parameters, forcing the caller to create an Optional instance, and should be solved by constructor overloading;

It should not be used for the parameters of the collection. The collection has already handled empty collections well, so there is no need to use Optional to wrap the collection;

It is not recommended to use the get method, if null, an error will be reported.

Here are some suggestions on how to deal with and avoid Java8 Optional errors:

Before using the get() method, be sure to use the isPresent() method to check whether the Optional object exists.

Do not use the isPresent() method and the orElse() method. Instead, use the orElseGet() method to allow the program to execute Supplier only when needed.

Optional<String> name = (null);
("Name: " + (() -> "Default Name"));

Do not use Optional as a parameter to a field or method of a class. This can cause classes or methods to become confusing and difficult to maintain. Use Optional for the return value whenever possible and only for parameters if necessary.

Avoid using Optional in recursive methods. Recursion is concise and clear in Java, but using Optional in recursive methods will cause a significant decline in the performance of the program.

Summarize

The above is what we will talk about today. This article briefly introduces the use of Optional objects and the situations that are not suitable for use of Optional objects.

This is all about this article about the usage of Optional classes in Java. For more related Optional classes in Java, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!