Optional class

Belongs to the java.util package

The Optional class is a null-capable container object, which is a good solution to null-pointer exceptions.

In short, Java8 provides an encapsulated container that can handle null logic or exceptions without fear. We need to put the value into the container, and then use the Api to handle the null pointer case easily.

The Optional class does not have a lot of source code, so you can take a look at the three static methods that initialize the contents of the container.empty,of,ofNullable), since all constructors are private, only factory methods can be used to get instances of Optional

The first line of the class defines a static constant EMPTY. The generic uses a wildcard. The second line is a value defined as final, which is used to store the value put into the container

    /**
     * Common instance for {@code empty()}.
     */
    private static finalOptional<? > EMPTY =new Optional<>();
    
    /** * If non-null, the value; if null, indicates no value is present */
    private final T value;
    
        
    private Optional(a) {
        this.value = null;
    }
Copy the code

Static method empty

This method simply converts the EMPTY static constant initialized at class loading into the generic T passed in and returns the value. You can call this method to return an Optional container with a value of NULL

    public static<T> Optional<T> empty(a) {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }
Copy the code

Declare an empty container with a value of type String

    Optional<String> empty = Optional.empty();
Copy the code

Static method of

The method is equivalent to passing in a value as the value in the container. After the value is passed in, the Optional constructor is called, which calls the objects.requirenonNULL method to determine whether the value is null. If null, NullPointerException is thrown; if not, a value is returned and assigned to the member property value

    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }
    
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }
Copy the code

RequireNonNull method of the Objects class called in the constructor

    public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }
Copy the code

A container is declared with a value of 123. The value initialized with the of method can be obtained by using the instance method get

        Optional<Integer> a = Optional.of(123);
        Integer integer = a.get();
Copy the code

Static method ofNullable

If the value is empty, the empty method will be called. If the value is not empty, the of method will be called

    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
Copy the code

Now let’s see how some instance methods are implemented. Okay

The get method

This is demonstrated in the of method, which returns the value of the current container and throws NoSuchElementException if value is null

    public T get(a) {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

Copy the code

IsPresent method

Check whether the value of value in the current container is empty and return a Boolean value

    public boolean isPresent(a) {
        returnvalue ! =null;
    }
Copy the code

If the value is null, an error is reported by calling get directly

if (optional.isPresent()) {
    p = optional.get();
}
Copy the code

IfPresent method

If the value in the current container is null, do nothing. If the value is not null, pass the value to the Consumer’s Accept

    public void ifPresent(Consumer<? super T> consumer) {
        if(value ! =null)
            consumer.accept(value);
    }
Copy the code

Java. Util. The function. The Consumer is a function of the JDK provide interface, contains a strip that has no return value parameter method: void the accept (T T), to a generic type parameter and perform some action. Since this is a functional interface, it can be written using traditional anonymous inner classes or Lambda expressions, which are not covered here

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}

Copy the code

Use: an anonymous inner class and a lambda expression, respectively. Since value is not null, the accept method is executed and the test string is printed

    Optional<String> data = Optional.of("test");
    
    data.ifPresent(new Consumer<String>() {
        @Override
        public void accept(String s) { System.out.println(s); }}); data.ifPresent(System.out::println);Copy the code

OrElse method

Check whether the value of value in the current container is empty. If it is not empty, return value; if it is empty, return the value passed in

    public T orElse(T other) {
        returnvalue ! =null ? value : other;
    }
Copy the code

Use: The test string is returned because the value in the container is empty

    Optional<String> empty = Optional.empty();
    System.out.println(empty.orElse("test"));
Copy the code

OrElseGet method

Check whether the value of the current container is empty. If it is not empty, value is returned. If it is empty, the Supplier instance’s get method is called,
provides that the return value type can only be of type T or a subtype of T

    public T orElseGet(Supplier<? extends T> other) {
        returnvalue ! =null ? value : other.get();
    }
Copy the code

Java. Util. Function: Supplier is provided by the JDK function interface, contains a free parameter method: T get (), used to return a generic parameter specifies the type of object

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get(a);
}

Copy the code

Use: written as an anonymous inner class and a lambda expression, respectively. Since value is null, the final return value is the Supplier instance get method return value

    Optional<String> empty = Optional.empty();
        
    String anonymity = empty.orElseGet(new Supplier<String>() {
        @Override
        public String get(a) {
            return "anonymity"; }}); String lambda = empty.orElseGet(() ->"lambda");
        
    System.out.println(anonymity);
    System.out.println(lambda);
    // Output two strings, "interim" and "lambda"
Copy the code

OrElseThrow method

Similar to orElseGet, the generic

function returns a value of type Throwable or a subtype of Throwable. If the value is null, an exception is thrown

    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if(value ! =null) {
            return value;
        } else {
            throwexceptionSupplier.get(); }}Copy the code

Use: an anonymous inner class and a lambda expression, respectively. Since the value is null, the final return value is returned by the Supplier instance’s GET method, which can be thrown up or caught by a try catch. This code throws any exception

    public static void main(String[] args) throws Exception {
        Optional<Object> empty = Optional.empty();

        // This comment will throw an exception returned by the following lambda expression
        empty.orElseThrow(new Supplier<Exception>() {
            @Override
            public IllegalArgumentException get(a) {
                return new IllegalArgumentException("value is null,from anonymity"); }});// This comment will throw an exception returned by the anonymous inner class
        empty.orElseThrow((Supplier<Exception>) () -> new IllegalArgumentException("value is null,from lambda"));
    }
Copy the code

The map method

Then determine whether the value of value in the current container is empty. If it is empty, call the empty method. If it is not empty, return the return value of ofNullable method. Mapper is a Function type, similar to the Supplier mentioned above. If the value is not empty, a Function can be executed to perform secondary logical data processing and return. The mapper Function has two generic types T and U. T is defined on the Optional class name, and public is followed by to declare that this method has a generic type U. The generic argument to Function specifies that the first argument is of type T or the parent type of T. The second argument is of type U or a subtype of U

    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if(! isPresent())return empty();
        else {
            returnOptional.ofNullable(mapper.apply(value)); }}Copy the code

Java. Util. The function. The function is a function of the JDK provide interface, methods to applay function is introduced to a value, return to another value

@FunctionalInterface
public interface Function<T.R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}
Copy the code

Use: written as an anonymous inner class and a lambda expression, respectively. Since the value of value is not empty, both variables accept the value 3 in Optional instances

    Optional<String> data = Optional.of("test");
    
    Optional<Integer> integer = data.map(new Function<String, Integer>() {
        @Override
        public Integer apply(String s) {
            return s.length() > 3 ? 1 : 0; }}); Optional<Integer> integer2 = data.map(s -> s.length() >3 ? 1 : 0);
    
    System.out.println(integer.get());
    System.out.println(integer2.get());
    // Prints two lines of string 3
Copy the code

FlatMap method

First check whether the parameter mapper is empty, then throw the null pointer exception, then check whether the value of the current container value is empty, then call empty method, call the return value of objects. requireNonNull function, and pass the mapper. Apply return value. If the apply method returns an empty value, it throws an exception. The method used is very similar to map, except that the map method is wrapped with the ofNullable method, while flatMap requires that the Optional container be returned directly

    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if(! isPresent())return empty();
        else {
            returnObjects.requireNonNull(mapper.apply(value)); }}Copy the code

Use: The applay method, written using an anonymous inner class, returns a container with the number 1 and calls the get output. The applay method, written using a lambda expression, throws an exception because it executes objects.requirenonNULL (null)

    Optional<String> data = Optional.of("test");
    
    Optional<Integer> integer = data.flatMap(new Function<String, Optional<Integer>>() {
        @Override
        public Optional<Integer> apply(String s) {
            return Optional.of(1); }}); System.out.println(integer.get());// Prints two lines of string 3
    
    data.flatMap(s -> null);
    RequireNonNull (null) requireNonNull(null)
Copy the code

The filter method

Predicate. If the predicate is empty, a null pointer will be raised. If the predicate is empty, the value of the value in the current container will be returned. If true returns the current instance, otherwise empty returns an empty container that filters the filter values. Predicate is also a function interface.

    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if(! isPresent())return this;
        else
            return predicate.test(value) ? this : empty();
    }
Copy the code

Java. Util. The function. The Predicate is a function of the JDK provide interface, the method of the test function is introduced to a value, returns a Boolean value

@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
}
Copy the code

Use: coded with an anonymous inner class and a lambda expression, and since the value of parisians is not empty, it outputs test and services.get() throws an exception

    Optional<String> data = Optional.of("test");
    Optional<String> rightly = data.filter(new Predicate<String>() {
        @Override
        public boolean test(String s) {
            return s.equals("test"); }}); Optional<String> falsely = data.filter(s -> s.equals(""));
        
    System.out.println(rightly.get());
    System.out.println(falsely.get());
    // the output will be "test"
    // Will then throw an exception for services.get because value is null
Copy the code

So far, all the methods and logic in Optional class have been read, the source code is clear and simple, read a clear understanding of the logic, the use of the tool class will have certain help. 🙂