当前位置 : 首页 » 文章分类 :  开发  »  Java8 Optional 笔记

Java8 Optional 笔记

Java8 Optional 笔记


Java Optional

空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional.of()或者Optional.ofNullable():创建Optional对象,差别在于of不允许参数是null,而ofNullable则无限制。

isPresent() 判断值是否存在

检查是否有值的另一个选择是 ifPresent() 方法。该方法除了执行检查,还接受一个Consumer(消费者) 参数,如果对象不是空的,就对执行传入的 Lambda 表达式:

opt.ifPresent( u -> assertEquals(user.getEmail(), u.getEmail()));

这个例子中,只有 user 用户不为 null 的时候才会执行断言。

orElse() 值为空时的默认值

orElse(),它的工作方式非常直接,如果有值则返回该值,否则返回传递给它的参数值

User user = null;
User user2 = new User("anna@gmail.com", "1234");
User result = Optional.ofNullable(user).orElse(user2);

orElseGet() 值为空时执行lambda表达式

第二个同类型的 API 是 orElseGet() —— 其行为略有不同。这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果:

User result = Optional.ofNullable(user).orElseGet( () -> user2);

orElse() 和 orElseGet() 的不同之处

当 Optional 对象为空而返回 orElse() 或 orElseGet()中的默认值时,行为并无差异,都会执行其中的代码。
但当 Optional 对象不为空时,orElse() 还会执行其中的代码,而 orElseGet()不会执行

public void givenPresentValue_whenCompare_thenOk() {
    User user = new User("john@gmail.com", "1234");
    logger.info("Using orElse");
    User result = Optional.ofNullable(user).orElse(createNewUser());
    logger.info("Using orElseGet");
    User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
}

这个示例中,两个 Optional 对象都包含非空值,两个方法都会返回对应的非空值。不过,orElse() 方法仍然创建了 User 对象。与之相反,orElseGet() 方法不创建 User 对象。

orElseThrow() 值不存在时抛异常

值不存在则抛出异常,存在则什么不做,有点类似Guava的Precoditions

public void whenThrowException_thenOk() {
    User result = Optional.ofNullable(user)
      .orElseThrow( () -> new IllegalArgumentException());
}

map()

User user = new User("anna@gmail.com", "1234");
String email = Optional.ofNullable(user)
  .map(u -> u.getEmail()).orElse("default@gmail.com");

使用示例

  • 为了防止从data中取出的Double类型数据为空导致的类型转换Exception,用Optional赋默认值0
bean.setIntegerValue((int)(double)Optional.ofNullable(data.getDoubleValue()).orElse(0.0));
bean.setIntegerValue((int)(double)Optional.ofNullable(data.getDoubleValue()).orElse(2.0));
  • chinaRegion非空则取其name,否则赋空
bean.setAddress(Optional.ofNullable(chinaRegion).map(ChinaRegion::getName).orElse(""));
  • 如果枚举serviceOrderStatus非空则取其描述信息,否则赋空
String orderStatusDesc = Optional.ofNullable(serviceOrderStatus).map(ServiceOrderStatus::getDesc).orElse("");
  • 先取request实体中的account_id,没有的话从userBean中取
Long accountId = Optional.ofNullable(request.getAccountId()).orElse(Optional.ofNullable(userBean).map(UserBean::getAccountId).orElse(null));
  • 分页默认值
paging.setOffset((long)Optional.ofNullable(request.getOffset()).orElse(DEFAULT_PAGE_OFFSET));
paging.setCount(Optional.ofNullable(request.getCount()).orElse(DERAULT_PAGE_COUNT));
  • 连环Optional,先取account_id,没有的话根据user_id查account_id,再没有的话取null
Long accountId = Optional.ofNullable(request.getAccountId()).orElse(Optional.ofNullable(baseUserMapper.selectAccountId(request.getUserId())).orElse(null));
  • 集合resultList按订单起始时间排序,没有起始时间则按结束时间,没有结束时间则使用默认值
// 整合后订单按创建时间倒序排序
Collections.sort(resultList, new Comparator<BaseBean>() {
    @Override
    public int compare(Order order1, Order order2) {
        Date order1CompareDate = Optional.ofNullable(order1.getOrderStartTime()).orElse(Optional.ofNullable(order1.getOrderEndTime()).orElse(DEFAULT_ORDER_START_TIME));
        Date order2CompareDate = Optional.ofNullable(order2.getOrderStartTime()).orElse(Optional.ofNullable(order2.getOrderEndTime()).orElse(DEFAULT_ORDER_START_TIME));
        return order2CompareDate.compareTo(order1CompareDate);
    }
});
  • 根据姓名集合查订单集合,如果结果不为空的话,取出其中的订单号构成List,否则新建List
List<Order> orderList = orderMapper.queryOrdersByNameList(request.getNameList());
List<String> orderNoList = Optional.ofNullable(orderList).map(ol -> ol.stream().map(Order::getOrderNo).collect(Collectors.toList())).orElse(Lists.newArrayList());
  • 从request中取起始时间和结束时间的Unix时间戳,有的话转为Date,没有的话设为null
Date startTime = Optional.ofNullable(request.getStartTimestamp()).map(t -> new Date(t * 1000)).orElse(null);
Date endTime = Optional.ofNullable(request.getEndTimestamp()).map(t -> new Date(t * 1000)).orElse(null);

理解、学习与使用 JAVA 中的 OPTIONAL
https://www.cnblogs.com/zhangboyu/p/7580262.html

JDK8新特性:使用Optional避免null导致的NullPointerException
https://blog.csdn.net/aitangyong/article/details/54564100


上一篇 ELK使用笔记

下一篇 Apache-kafka

阅读
1,076
阅读预计5分钟
创建日期 2018-08-29
修改日期 2018-09-04
类别
标签
百度推荐