Great Java-Optional null alternative treatment

Optional principal problem is the infamous null pointer exception (NullPointerException). There is an optional value that contains wrapper classes, which means Optional classes can contain both objects can also be empty.
May produce abnormalities in this code space;

String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();
//需要检查:
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();
            }
        }
    }
}

Optional classes are still dependent on the function interface that set of things:

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

 

Oriented programming interface is to make a go in the end. Only one private field:

private final T value;

Native code is quite simple:

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

    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

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

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

Creating Optional package instance

Built empty

        Optional<Insurance> emptyOpt = Optional.empty();
        try {
            Insurance obj = emptyOpt.get();
            System.out.println("不为空");
        } catch (NoSuchElementException ex) {
            System.out.println("为空");
        }

EmptyOpt try to access the variable values ​​cause NoSuchElementException, because the soundtrack Code:

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

Construction may be empty (ofNullable not throw an exception)

Optional<Insurance> opt = Optional.ofNullable(null);

Not abnormally
so amazing, because the native code has been sentenced to empty, given the private value became empty (), which does not throw an exception also have a problem that in instances when the consumer, or to filter out empty value.

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

Throw an exception when construction is empty (that is, of non-empty)

    public static void whenCreateOfEmptyOptional_thenNullPointerException() {        
        Insurance ins = new Insurance();        
        Optional<Insurance> opt = Optional.of(ins);
        ins=null;
        try {
            opt = Optional.of(ins);
            System.out.println("不为空");
        } catch (NullPointerException ex) {
            System.out.println("为空");
        }        
    }

It will enter exception. Tracking native code found out the reason:

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

Value Optional object access

get

One way to retrieve the actual value of the object instance is to use the Optional get () method:

@Test
public void whenCreateOfNullableOptional_thenOk() {
String name = "John";
Optional<String> opt = Optional.ofNullable(name);

assertEquals("John", opt.get());
}

This method throws an exception if the value is null. To avoid exceptions, you can choose to first verify whether there are values:

@Test
public void whenCheckIfPresent_thenOk() {
User user = new User("[email protected]", "1234");
Optional<User> opt = Optional.ofNullable(user);
assertTrue(opt.isPresent());

assertEquals(user.getEmail(), opt.get().getEmail());
}

The use ifPresent

Native code:

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

Only when the value is not empty, before the implementation of method consumers accept, it is relatively safe.

    public static void printName(Insurance obj)
    {
        Optional.ofNullable(obj).ifPresent(u ->  System.out.println("The name is : " + u.getName()));
    }

        Insurance obj = new Insurance();
        obj.setName("张三");
        Insurance objNull = null;        
        printName(obj);
        printName(objNull);

//输出:The name is : 张三

The use isPresent

With feeling ifPresent, then you do not need to judge isPresent empty, otherwise I feel very long-winded.

orElse use

Return to the default value when the object is empty. The way it works is straightforward, if the value of the value is returned, otherwise the value parameter passed to it.

Insurance obj = new Insurance();
obj.setName("张三");
Insurance objNull = null;    
Insurance result = Optional.ofNullable(objNull).orElse(obj);
System.out.println(obj.hashCode());
System.out.println(result.hashCode());

The actual result is returned obj, instead of null.

filter use

filter () method takes as parameters Predicate object, the object is used to filter Optional, if they meet the conditions of Predicate returns Optional object itself, otherwise an empty Optional objects

public static void filterAge(Student student)
{
    Optional.ofNullable(student).filter( u -> u.getAge() > 18).ifPresent(u ->     System.out.println("The student age is more than 18."));
}

Use the map

parameter map () method of Function (function interface) objects, map () method Optional the wrapper object calculates a Function functions, and packaged into new Optional objects (type wrapper object may vary)
native code:

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

The following code, the first () method is configured with ofNullable a Optional <Student> object, and then calculate the age of the students using map (), returns Optional <Integer> object (if the student is null, returns the map () method returns an empty Optinal Object)

public static Optional<Integer> getAge(Student student)
{
    return Optional.ofNullable(student).map(u -> u.getAge()); 
}

flatMap use

With map () method is different, the reference function's return value Function type Optional <U> type, rather than U type, such flatMap () Optional objects capable of a two-dimensional map into a one-dimensional object,
sum , map into what is out of the same dimensions, flatMap to shoot flat results.

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

//例子
        Optional<String> nonEmptyGender = Optional.of("male");
        Optional<String> emptyGender = Optional.empty();

        System.out.println("Non-Empty Optional:: " + nonEmptyGender.map(String::toUpperCase));
        System.out.println("Empty Optional    :: " + emptyGender.map(String::toUpperCase));

        Optional<Optional<String>> nonEmptyOtionalGender = Optional.of(Optional.of("male"));
        System.out.println("Optional value   :: " + nonEmptyOtionalGender);
        System.out.println("Optional.map     :: " + nonEmptyOtionalGender.map(gender -> gender.map(String::toUpperCase)));
        System.out.println("Optional.flatMap :: " + nonEmptyOtionalGender.flatMap(gender -> gender.map(String::toUpperCase)));

The package may be null

Use ofNullable, such as in some key map is used it is empty:

Optional<Insurance> opt = Optional.ofNullable(map.get("someNullKey"));

 

Guess you like

Origin www.cnblogs.com/starcrm/p/12410903.html