Java8 操作空指针的优雅处理

2,807 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

Java8 新特性中包括了Stream相关的操作,由于是流式编程,在项目中使用时十分方便。但是,流式操作的过程中,当中间的结果对象有存在为null的可能时,整个流式操作进行时就会报出空指针异常。

1. NullPointerException

NullPointerException,即空指针(引用)异常,是一种运行时异常,在对一个null对象进行相关属性或方法调用时产生,会导致程序运行异常。

在项目开发的业务处理中,处理最多的异常基本就是空指针异常,空指针异常的适当处理能够让项目更加稳定。

本文主要讲解在Java8流式操作中如何优雅的处理NullPointerException。

2. Java8中处理NullPointerException

现有的业务场景中存在订单和产品类:Order、Product,其关系如下所示:

public class Production {
    private Integer productionId;
    private String productName;
    private ProductSpecification productSpec;
}

public class ProductSpecification {
    private Integer productSpecId;
    private String productSpecName;
}

2.1 Java8之前业务逻辑处理

如果我们需要从订单中获取指定商品的信息,则需要有操作:

//判断条件复杂
public String getSpecName(Product product) {
    if (product != null && product.getSpec != null) {
            return product.getSpec.getSpecName();
    }else {
        return "";
    }
}

//逻辑臃肿
public String getSpecName(Product product) {
    if (product != null) {
            Specification spec = product.getSpec;
            if (spec != null) {
                return spec.getSpecName();
            } else {
                    return "";
            }
    }else {
        return "";
    }
}

可以看出我们在对一个对象进行操作时,需要对操作过程涉及到的对象进行判空操做,大量的判空操作和if..else导致代码十分臃肿。

2.2 Java8操作展身手

针对频繁的判空操作和代码臃肿问题,我们可以使用Java8的Stream流式操作来实现对象取值。

public void print(Product product){
    Optional.ofNullable(production)
            .map(Production::getProductSpec)
            .ifPresent(specInfo -> System.out.println(specInfo.getSpecName()));
}

这一段代码的逻辑可以理解为:

  1. 如果production为null,则返回空的Optional对象并不输出任何值
  2. 如果production不为null,则通过getProductSpec方法获取production中的productSpec属性
  3. 如果productSpec属性存在,则输出其productSpecName值。

2.3 Optional

Optional是Java8新加入的容器,这个容器中有1个或者0个元素,Optional的出现就是用来防止NullpointException的。常见的方法有:

  • Optional.empty():创建一个空的Optional实例
  • Optional.of(T t) : 创建一个Optional 实例,为null时报异常
  • Optional.ofNullable(T t):若t 不为null,创建Optional 实例,否则创建空实例
  • isPresent() : 判断容器中是否有值
  • ifPresent(Consume lambda) :容器若不为空则执行括号中的Lambda表达式
  • orElse(T t) : 获取容器中的元素,若容器为空则返回括号中的默认值
  • orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回s 获取的值
  • map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
  • flatMap(Function mapper):与map 类似,要求返回值必须是Optional
  • T get() :获取容器中的元素,若容器为空则抛出NoSuchElement异常

3. 总结

Java8流式操作增加了诸多的便利性,但是在普通的流式操作使用时仍然会存在NullPointerException,因此在实际项目的业务处理逻辑中还要需要多考虑,减少异常对系统稳定的影响。

Optional作为新增加的用于优雅的处理NullPointerException,其中提供了很多方法都对null进行了判断,是一种很合适对象操作方法。

本篇文章仅作为Optional入门学习,开启新大门的钥匙,在之后的日子里不断的深入学习。

Java都16了,Java8还不快掌握起来啦!