基础知识

Optional解决NPE问题

2020-05-09  本文已影响0人  yueming15899

NPE问题

NPE 即(java.lang.NullPointException):空指针异常,在日常编程中常常会遇到的问题。通常需要使用者对传入参数或者调用返回结果进行空指针(null)判断,java8之前一般的代码如下:

    public String getUserAddressArea(User user) {
        if (user != null) {
            if (user.getAddress() != null) {
                return user.getAddress().getArea();
            }
        }
        return null;
    }

如果业务对象嵌套了多层对象,那么如果按照上面的写法if也会嵌套多层。虽然可以使用卫语句进行优化但是代码依旧丑陋(多层嵌套会有多个if,如果还有其它判断条件则会使得if更加复杂)

  //卫语句减少嵌套  
  public String getUserAddressArea(User user) {
        if (user == null) {
            return null;
        }
        if (user.getAddress() == null) {
            return null;
        }
        return user.getAddress().getArea();
    }

java8提供了Optional更优雅的方式应对上述问题

    //使用Optional避免NPE
    public String getUserAddressArea(User user) {
        return Optional.ofNullable(user)
                .map(u -> u.getAddress())
                .map(address -> address.getArea())
                .orElseGet(() -> null);
    }

     //附加其它条件
    public static String getUserAddressArea(User user) {
        return Optional.ofNullable(user)
                .filter(u -> "yueming".equals(u.getName()))
                .map(u -> u.getAddress())
                .map(address -> address.getArea())
                .orElseGet(() -> null);
    }

上面就是Optional的基本用法,下面简单介绍一下里面用到的一些方法(具体请参照官方的API文档)

常用方法

    // 使用flatMap
    public static String getUserAddressArea(User user) {
        return Optional.ofNullable(user)
                .filter(u -> "yueming".equals(u.getName()))
                .flatMap(u -> u.getAddress())
                .map(address -> address.getArea())
                .orElseGet(() -> null);
    }
    //User 类中的getAddress方法
    public Optional<Address> getAddress() {
        return Optional.ofNullable(address);
    }
    //使用map  
    public static String getUserAddressArea(User user) {
        return Optional.ofNullable(user)
                .filter(u -> "yueming".equals(u.getName()))
                .map(u -> u.getAddress())
                .map(address -> address.getArea())
                .orElseGet(() -> null);
      }
    // User 类中的getAddress方法
     public Address getAddress() {
        return address;
    }

Optional原理

原理其实很简单就是把要处理的对象传入Optional,本来应该由用户来判断的是否为null的逻辑封装起来了而已(将经常用到的逻辑封装起来复用代码让代码更加优雅),可自行查看Optional源代码了解。

public final class Optional<T> { 
   private static final Optional<?> EMPTY = new Optional<>();
   private final T value;
   // 构造Optional
    private Optional() {
        this.value = null;
    }
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }
    
    //判断是否为空 核心还是判断是不是为null,filter,map,flatMap方法均有调用isPresent
    //其它orElse、orElseGet、orElseThrow、ifPresent、get方法也均是采用了value != null来做判断。
    public boolean isPresent() {
        return value != null;
    }
    ...
}

上一篇下一篇

猜你喜欢

热点阅读