Optional使用教程

使用Java8的新特性 Optional 代替 if - else 解决空指针问题

静态构造方法

JDK提供三个静态方法来构造一个`Optional`

public final class Optional<T> {
    
    private static final Optional<?> EMPTY = new Optional<>();
    private final T value;

    // 该方法用来构造一个空的 Optional,如果 Optional 中的 value 为 null 则该 Optional 为不包含值的状态
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

    // 通过一个非 null 的 value 来构造一个 Optional,
    // 返回的 Optional 包含了 value 这个值。对于该方法,传入的参数一定不能为 null,否则便会抛出 NullPointerException
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    // 该方法和 of 方法的区别在于,传入的参数可以为 null,如果为 null 的话,返回的就是 Optional.empty()
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
}

常用方法

isPresent() / ifPresent()

// 如果值存在返回true,否则返回false
public boolean isPresent() {
    return value != null;
}

// 如果Optional实例有值则为其调用consumer ,否则不做处理。
public void ifPresent(Consumer<? super T> consumer) {
    if (value != null)
        consumer.accept(value);
}

测试

 public class OptionalTest {
     public static void main(String[] args) {
         User user = new User();
         Optional<User> optional = Optional.ofNullable(user);
         optional.ifPresent(s -> System.out.println(s));
     }
 }

Get()

获取Optional中的值,这个值也就是我们的值,Optional相当于就是一个外壳。

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

orElse() / orElseGet() / orElseThrow()

// 如果Optional中的值不为空,则返回Optional中的值,如果为空,则返回other值,
public T orElse(T other) {
    return value != null ? value : other;
}

// 如果Optional中存在值,则返回值,否则返回other调用的结果
public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}

// 如果Optional中的值存在,则返回值,值不存在,则抛出异常函数Supplier中的异常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

测试

 String value = "2";
 String orElse = Optional.ofNullable(value).orElse("1");  
 System.out.println(orElse);  //2  
         
 String value = null;
 String orElse = Optional.ofNullable(value).orElse("1"); 
 System.out.println(orElse);  //1
 
 -------------------------------------------------------
 
  public class OptionalTest {
     public static void main(String[] args) {
         String value = null;
         String orElse = Optional.ofNullable(value).orElseGet(OptionalTest::get);
         System.out.println(orElse);  // 123
         
         String value = "2";
         String orElse = Optional.ofNullable(value).orElseGet(OptionalTest::get);
         System.out.println(orElse);  // 2                                       
     }
 ​
     public static String get(){
         return "123";
     }
 }
 
  -------------------------------------------------------
  
   public class OptionalTest {
     public static void main(String[] args) {
         String value = null;
         String orElse = Optional.ofNullable(value).orElseThrow(() -> new RuntimeException("不存在值"));
         System.out.println(orElse);
     }
 }

map() / flatMap()

  • map(Function):如果 Optional 不为空,应用 Function 于 Optional 中的内容,并返回结果。否则直接返回 Optional.empty

  • flatMap(Function):同 map(),但是提供的映射函数将结果包装在 Optional 对象中,因此 flatMap() 不会在最后进行任何包装。

以上方法都不适用于数值型 Optional。一般来说,流的 filter() 会在 Predicate 返回 false 时移除流元素。而 Optional.filter() 在失败时不会删除 Optional,而是将其保留下来,并转化为空。

// 将Optional中的值作为参数传递到map中,如果传入的值为空,则返回一空的Optional对象,相当于Optional.empty(), 
// 如果不为空,我们可以返回一个可以描述描述结果的返回值(Optional中的值,这个值可以重新赋值)
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));
    }
}

// 如果Optional中值存在,那么返回一个基于Optional的值(如Optional),
// 如果Optional中的值不存在,则返回一空的Optional对象,相当于Optional.empty(),
// 与map不同, map返回的是一个值,而flatMap返回一个基于Optional的值
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));
    }
}

测试

 public class OptionalTest {
     public static void main(String[] args) {
         User user = null;
         Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap);
         System.out.println(optional); //Optional.empty
         
         User user = new User();         
         user.setUsername("Admin");           
         Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap);        
          System.out.println(optional); // Optional[Admin]

     }
 ​
     public static String getMap(User user){
         return user.getUsername();
     }
     
 -------------------------------------------------------
 
       User user = new User();         
       user.setUsername("Admin");                  
       Optional<String> optional = Optional.ofNullable(user).flatMap(OptionalTest::getFlatMap);         
       System.out.println(optional);      
   } ​     
   public static Optional<String> getFlatMap(User user){         
       return Optional.ofNullable(user).map(User::getUsername);     
   }

filter()

将Optional中的值作为参数传入,如果符合规则,那么返回一个Optional对象,否则返回一个空的Optional 对象(Optional.empty)

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

实战

ifPresent(),这是一个终端操作,如果value存在则会调用指定的消费方法

// 获取 book 的值,若 book 为 null 则返回默认值
String book = Optional.ofNullable(person).map(Person::getBook).orElse("default");

// person 不为 null 则打印薪水
Optional.ofNullable(person).ifPresent(p -> System.out.println(p.getSalary()));
​
​// 若 book 为 null,则设置默认值
 Optional.ofNullable(person)
                .map(Person::getComputer)
                .ifPresent(c -> c.setBrandName("default name"));
                
 Optional.ofNullable(person)
                .map(Person::getComputer)
                .ifPresent(this::consumerTest);
​
 public void consumerTest(Computer computer){
        System.out.println("consumer test");
        System.out.println(computer);
    }
​
// 获取brand,若 brandName 为 "",则抛出异常
// 因为 map只能过滤掉 null 值,而在工作中通常还需要做其它的判断,所以我们可以使用 map 去解析实体类中的某个属性,然后使用 filter 进行对应的过滤
String brand = Optional.ofNullable(person)
                .map(Person::getComputer)
                .map(Computer::getBrandName)
                .filter(b -> !b.equals(""))
                .orElseThrow(() -> new NumberFormatException("品牌为空"));
        System.out.println("brand: " + brand);

参考文献:

Java8之熟透Optional - 掘金

聊一聊Java8 Optional,让你的代码更加优雅 - 掘金

猜你喜欢

转载自blog.csdn.net/weixin_46058921/article/details/126859180