【业务功能篇137】Java8特性:Optional

 实际开发中会遇到一个大对象,链式的处理数据,并且还不确定是否为空,如果是简单的对象嵌套判断可以直接就 == null, 但是如果还有一系列的逻辑处理,那么新特性Optional一定能更优雅简洁的实现

  •     Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
  •     Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
  •     Optional 类的引入很好的解决空指针异常。

Optional的作用:

         Optional作为npe(NullPointerException)的解决方案,它的最主要作用就是保证操作一个null对象时,流程依旧会流转下去,不会不经开发者同意就向上抛出npe(是否抛取决于开发者的业务)。可以把这种功能简单的理解为Optional的每一步操作都会进行一个非空校验,空和非空会各自执行一个分支语句。

注意事项

  • 如果已知对象不可能为空,则尽量不要使用这个类来增加代码的复杂度。
  • 如果条件判断比较简单,一般也不会用到Optional。
  • 鉴于大多数情况下,开发者都不会主动去校验对象是否为null,从而导致程序中断,所以一般推荐将Optional用于查询结果的非空校验。

1. if-else操作

    是Optional实际运用的基础操作,自然地,代码里的任意if-else非空判断都能与Optional相互替代。

    注意事项:

        当orElse通过方法来获取默认值时,orElse中的方法将总是会被执行(因为该方法接受的是一个具体值,为了获取该具体值,总是会在调用orElse方法前执行其参数中的方法)
        orElseGet则不同,它只在值为空时才会执行该方法(它的参数是一个方法引用,而非具体值)
        如果只是需要一个固定的默认值,可以使用orElse;当需要方法或数据库执行结果时,都推荐使用orElseGet。

Optional写法:

public static Product selectProductOtherwiseDefault(Long productId) {
    Optional<Product> optional = Optional.ofNullable(getProduct(productId));
    optional.ifPresent(OptionalUsage::setProductInfo);
    return optional.orElse(getDefaultProduct());
    //  return optional.orElseThrow(BusinessException::new);
    //  return optional.orElseGet(OptionalUsage::getDefaultProduct);
}


if-else写法:

public static Product selectProductOtherwiseDefault1(Long productId) {
    Product product = getProduct(productId);
    if (product != null) {
        setProductInfo(product);
    } else {
        product = getDefaultProduct();
        //  throw new BusinessException();
    }
    return product;
}

 

 

2. 对象属性非空校验

    如果要获取对象的属性,我们不知道这个对象是否为null,以及它的属性是否为null时,可以使用Optional来代替那些非空校验。

    注意事项:

        map方法映射的结果仍然会被Optional封装,后续仍能对该方法返回的null值进行操作
        flatMap则是直接返回的映射结果,如果结果为null,该方法会抛出npe

Optional写法:

public static List<ProductPicture> getProductPicture(Product product) {
    Optional<Product> optional = Optional.ofNullable(product);
    return optional
            .map(Product::getProductDetail)
            .map(ProductDetail::getProductPictures)
            .orElse(null);
}


非空校验写法:

public static List<ProductPicture> getProductPicture1(Product product) {
    if (product != null) {
        ProductDetail productDetail = product.getProductDetail();
        if (productDetail != null) {
            return productDetail.getProductPictures();
        }
    }
    return null;
}

对象层级越多,这种写法就越显得臃肿、越难于阅读。

3. 嵌套非空校验

  •     多个对象嵌套,在不清楚某个对象是否为null时,想对某个嵌套对象做某些操作,就可以用到Optional。

Optional写法:

public static void setProductInfo(Product product) {
    Optional<Product> optional = Optional.ofNullable(product);
    optional.ifPresent(product1 -> {
        // getBrand一般代表其它方法的结果或sql查询结果
        product1.setBrand(Optional.ofNullable(product1.getBrandId()).map(OptionalUsage::getBrand).orElse(null));
        product1.setCategory(Optional.ofNullable(product1.getCategoryId()).map(OptionalUsage::getCategory).orElse(null));
    });
}


非空校验写法:

public static void setProductInfo1(Product product) {
    if (product != null) {
        Long brandId = product.getBrandId();
        Long categoryId = product.getCategoryId();
        if (brandId != null) {
            product.setBrand(OptionalUsage.getBrand(brandId));
        }
        if (categoryId != null) {
            product.setCategory(OptionalUsage.getCategory(categoryId));
        }
    }
}

这种写法很常见,但是大多数开发者都可能会忘记做这一部分的非空校验,从而导致下游服务或方法抛出npe异常,从而中断整个程序的执行。

4. 其它校验与非空校验组合

    其实大部分情况下,我们除了校验对象是否为空,还会对它的某个属性进行校验,从而来组成一个完整的if-else组合。如果Optional仅支持非空校验,那么使用场景其实有限的,索性Optional还支持非空校验外的其它校验来过滤数据。

Optional写法:

 通过校验后,仍然可以像前几列一样执行if-else操作
 

public static boolean checkProductIntegrityThenUpdate(Product product) {
    Optional<Product> optional = Optional.ofNullable(product)
            .filter(product1 -> null != product.getProductDetail() && null != product.getCategory() && anyOtherCheck());
    optional.ifPresent(OptionalUsage::updateIntegrityProductInfo);
    return optional.isPresent();
}


组合校验写法:

public static boolean checkProductIntegrityThenUpdate1(Product product) {
    boolean check = product != null && null != product.getProductDetail() && null != product.getCategory() && anyOtherCheck();
    if (check) {
        updateIntegrityProductInfo(product);
    }
    return check;
}

Java 8 Optional在实际业务场景中的运用_jdk8 optional list 业务转换写法-CSDN博客

  • 24
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值