[Java] Learn how to use Optional correctly

Optional is a convenient API that reduces null check if statements ... I had a time when I was thinking that way.

Take the ʻIntegerList` class as an example to get a list and elements of Integers containing nulls.

IntegerList.java


import java.util.List;
import java.util.Arrays;

public class IntegerList {
    //List of Integers containing null
    private final static List<Integer> INTEGER_LIST = Arrays.asList(new Integer[]{1, 2, null});
    
    public static Integer get(int index) {
        return INTEGER_LIST.get(index);
    }
}

Prepare a Main class that gets a numeric element from the above ʻIntegerList, adds 100, and outputs it. Considering the possibility that the return value of ʻIntegerList # get is null, set -1 if it is null.

When not using Optional

Main.java


/**
 *Get the value from IntegerList, add 100 and output
 **/
public class Main {
    public static void main(String[] args) throws Exception {
        Integer value = IntegerList.get(2);
        //If null-Set to 1
        if (value == null) {
            value = -1;
        }
        value += 100;
        System.out.println("result:" + value);
    }
}

Result: 99

When using Optional

You can write it as follows:

Main.java


import java.util.Optional;

/**
 *Get the value from IntegerList and add 100
 **/
public class Main {
    public static void main(String[] args) throws Exception {
        //Get the element from the IntegerList class. If null-Set to 1.
        Integer value = Optional.ofNullable(IntegerList.get(2)).orElse(-1);
        value += 100;
        System.out.println("result:" + value);
    }
}

The if statement disappeared and I could write it in one line.

The code is clean! Optional Convenient! !! It seems that we shouldn't end with the story.

What's wrong

If you want to loosely couple relationships between classes It seems strange that the calling Main class makes the return value of ʻIntegerList # get Optional. I was able to write the code to make it Optional because I knew that the return value of ʻIntegerList # get could be null. What you know is that the relationship is more or less close. And, conversely, if you do not notice the possibility of becoming null, neither Optionalization nor null check will be written, and you will allow the occurrence of NullPointerException.

solution

Instead of the caller making the return value Optional, the callee returns Optional as the return value.

IntegerList.java


import java.util.List;
import java.util.Arrays;
import java.util.Optional;

public class IntegerList {
    //An array of Integers containing null
    private final static List<Integer> INTEGER_LIST = Arrays.asList(new Integer[]{1, 2, null});
    
    //Since the return value may contain null, wrap it in Optional and return it.
    public static Optional<Integer> get(int index) {
        return Optional.ofNullable(INTEGER_LIST.get(index));
    }
}

Main.java


import java.util.Optional;

/**
 *Get the value from IntegerList and add 100
 **/
public class Main {
    public static void main(String[] args) throws Exception {
        //Get the element from the IntegerList class. If null-Set to 1.
        Optional<Integer> optionalValue = IntegerList.get(2);
        Integer value = optionalValue.orElse(-1) + 100;
        System.out.println("result:" + value);
    }
}

By setting Optional as the return value, it is possible to clarify that the return value of ** ʻIntegerList # getmay be null, and to force the caller to code considering null. ** ** This will prevent the caller from forgetting to write the null verdict and getting aNullPointerException`.

References and citations

If the above doesn't work, you can refer to the following.

Summary of stories and usage of Optional not Serializable

Therefore, the usage of Optional is basically only as the return value of the method, and it is better not to use it for the next field.

Use Optional type instead of null in Java8

The advantage is that wrapping the value in this prohibits direct tampering, thereby syntactically forcing the program to build on the premise that "the value may not be returned". In short, it's the syntax (class) for forcing null checking.

re: Maybe / Nullable / Optional doesn't really fit me.

Java Optional seems to be supposed to be used as the return value of the method, not to be used for arguments or fields. Given that Java's Optional is a reference type, it can be null, so it's understandable to some extent that it shouldn't be used as an argument.

Java Optional

Java often has a method that "returns a value, but cannot return a value only in certain cases". 例えばjava.util.Map#get()は、キーがあればそれに紐付く値を返すが、キーが無い場合はnullを返す。 For example, String # indexOf () returns the position of the found character, but returns -1 if not found. The role of Optional is to express the return value of such a method.

Try using Java 8 Optional

The advantage of using Optional is that you can make it clear in your code that its value may not be there. In the above example, the acquired left and right are optional, so you will be forced to describe the processing in the case of empty without being careful.

10 Tips To Handle Null Effectively

As I already said, Optional was designed to indicate missing return values. One tempting case that it was not designed for and surely is not necessary is class’ fields. Although it is in English, it was helpful because it was packed with thoughts on coding for null.

Recommended Posts

[Java] Learn how to use Optional correctly
How to use java Optional
[Java] How to use Optional ②
[Java] How to use Optional ①
[Java] How to use Map
[Java] How to use Map
How to use java class
[Java] How to use removeAll ()
[Java] How to use string.format
How to use Java Map
How to use Java variables
How to use Java HttpClient (Get)
How to use Java HttpClient (Post)
[Java] How to use join method
How to learn JAVA in 7 days
[Processing × Java] How to use variables
[Java] How to use LinkedHashMap class
[JavaFX] [Java8] How to use GridPane
[Java] How to use List [ArrayList]
How to use classes in Java?
[Processing × Java] How to use arrays
How to use Java lambda expressions
[Java] How to use Math class
How to use Java enum type
Multilingual Locale in Java How to use Locale
[Java] How to use the File class
[Java] How to use the hasNext function
How to use submit method (Java Silver)
[Java] How to use the HashMap class
[Easy-to-understand explanation! ] How to use Java instance
[Java] How to use the toString () method
Studying how to use the constructor (java)
How to use Java classes, definitions, import
[Easy-to-understand explanation! ] How to use Java polymorphism
[Java] [Maven3] Summary of how to use Maven3
How to use Java Scanner class (Note)
[Processing × Java] How to use the function
[Easy-to-understand explanation! ] How to use ArrayList [Java]
[Java] How to use the Calendar class
[Easy-to-understand explanation! ] How to use Java overload
try-catch-finally exception handling How to use java
[Easy-to-understand explanation! ] How to use Java encapsulation
How to use rbenv
How to use letter_opener_web
How to use with_option
How to use java.util.logging
How to use map
How to use Twitter4J
How to use active_hash! !!
How to use hidden_field_tag
[How to use label]
How to use identity
How to use hashes
How to use JUnit 5
How to use Dozer.mapper
How to use Gradle
How to use org.immutables
How to use java.util.stream.Collector
How to use VisualVM
How to use Map
[Java] How to use FileReader class and BufferedReader class