Fork me on Gitee

JDK 1.8 Optional使用技巧

一、 Optional 构造方法

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

1.1 Optional.empty()

Optional.empty(),该方法用来构造一个空的Optional。即Optional里面不好看

1.2 Optional.of()

Optional.of(T value),该方法通过传入一个非null的value来构造一个Optional,返回Optional包含了value这个值。对于该方法,传入的参数一定不为空,否则会抛出NullPointerException

1.3Optional.ofNullable()

Optional.ofNullable(T value),该方法和of方法的区别在于,传入的参数可以为null。当传入参数为null时,就会返回Optional.empty()。

2. Optional相关方法

2.1 isPresent

判断是否引用缺失可以使用optional.isPresent();,底层使用if(xxx== null),返回boolean值。不推荐使用。

image-20230309164036237

2.2 ifPresent

如果Optional中有值,则对该值调用consumer.accept,否则什么也不做。

image-20230309171020293

Optional<Object> optional = Optional.ofNullable("zhangsan");
//打印optional传入的对象
optional.ifPresent(System.out::println);

2.2 orElse

如果Optional有值,则将其返回,否则返回orElse()方法传入的参数。

User user = Optional
  .ofNullable(getUserById(id))
  .orElse(new User(0,"Unknown User"))
System.out.println("Username is: " + user.getUsername());

2.3 orElseGet

orElseGet和orElse的方法区别在于,orElseGet方法传入的参数为一个super接口的实现。当Optional有值时,返回值。当Optional中没有值的时候,返回从该Suppiler获得值。

User user = Optional
        .ofNullable(getUserById(id))
        .orElseGet(() -> new User(0, "Unknown"));
System.out.println("Username is: " + user.getUsername());

2.4 orElseThrow

orElseThrow与orElse方法的区别在于,orElseThrow方法当Optional中有值的时候,返回值,没有的时候抛出异常,抛出的异常由传入的exceptionSuppiler提供。

User user = Optional
        .ofNullable(getUserById(id))
        .orElseThrow(() -> new EntityNotFoundException("id 为 " + id + " 的用户没有找到"));

2.5 map

当optional为空的时候,返回empty(),否则返回一个新的Optional,该Optional包装的是mapper以value做出输入的输出值。

2.6 flatMap

flatMap和map方法的区别是,map方法参数中的mapper输出的是值,map方法会使用Optional.ofNullable将其包装成optional,而flatMap要求参数中的mapper输出的就是Optional。

2.7 filter

filter方法接收一个Predicate来对Optional中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个Optional;否则返回Optional.empty

Optional<String> username = Optional
        .ofNullable(getUserById(id))
        .filter(user -> user.getId() < 10)
        .map(user -> user.getUsername());
       
System.out.println("Username is: " + username.orElse("Unknown"));

有了Optional,可以方便且优雅的在代码中处理null值,而不是需要通过if(Object!=null)来判断值是否为空,如果JDK1.8版本以前,可以考虑使用google的guava库,早在JDK 的年代,Guava就提供了Optional的实现。

3. 综合案例

@Data
public class SkuVO {
    private Long skuId;
    private Price price;
}
@Data
public class Price {
    private BigDecimal mallPrice;
    private BigDecimal sellPrice;
}

有一个SkuVO对象,里面包含了一个skuId和一个price对象,price对象里面有市场价和成本价。假设有需求获取sku里面的mallPrice并返回。按照jdk 1.8以前的思路一般这么写

private static BigDecimal fetchMallPrice1(SkuVO skuVO) throws Exception {

        if (skuVO != null) {
            Price price = skuVO.getPrice();
            if (price != null) {
                BigDecimal mallPrice = price.getMallPrice();
                if (mallPrice != null) {
                    if (mallPrice.compareTo(new BigDecimal("10")) == 1) {
                        return mallPrice;
                    }
                }
            }
        }

在真实的项目中,这样的写法实在是太常见了。各种非空判断才敢继续执行,否则会抛出NullPointerException,但是这样的代码,if嵌套太深,可读性非常差。

JDK 1.8的写法可以改造为

 private static BigDecimal fetchMallPrice2(SkuVO skuVO)throws Exception{
        return Optional.ofNullable(skuVO)
                .map(s->s.getPrice())
                .map(p -> p.getMallPrice())
                .filter(m -> m.compareTo(new BigDecimal(10)) ==1)
                .orElse(new BigDecimal(10));

    }

Optional.ofNullable(skuVO)首先构造一个Optional,map(Function<? super T, ? extends U> mapper)接收一个Funtion,filter过滤map返回的值,最后通过orElseThrow抛出异常。

posted @ 2023-03-09 18:03  shine-rainbow  阅读(282)  评论(0编辑  收藏  举报