如何优雅的解决空指针异常——Java 8 Optional 类


作为后端程序员,空指针异常无疑是最常见,也是最头痛的问题之一…
那么作为互联网最酷的一批人,应该如何优雅的处理这类问题呢😝

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

类声明:

//以下是一个 java.util.Optional<T> 类的声明:
public final class Optional<T>
extends Object

类方法:

  1. static <T> Optional<T> empty()
    返回空的 Optional 实例。
  2. boolean equals(Object obj)
    判断其他对象是否等于 Optional。
  3. Optional<T> filter(Predicate<? super <T> predicate)
    如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。
  4. <U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)
    如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional
  5. T get()
    如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException
  6. int hashCode()
    返回存在值的哈希码,如果值不存在 返回 0。
  7. void ifPresent(Consumer<? super T> consumer)
    如果值存在则使用该值调用 consumer , 否则不做任何事情。
  8. boolean isPresent()
    如果值存在则方法会返回true,否则返回 false。
  9. <U>Optional<U> map(Function<? super T,? extends U> mapper)
    如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。
  10. static <T> Optional<T> of(T value)
    返回一个指定非null值的Optional。
  11. static <T> Optional<T> ofNullable(T value)
    如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。
  12. T orElse(T other)
    如果存在该值,返回值, 否则返回 other。
  13. T orElseGet(Supplier<? extends T> other)
    如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。
  14. <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
    如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
  15. String toString()
    返回一个Optional的非空字符串,用来调试

Optional 实例


import java.util.Optional;
 
public class Java8Tester {
   public static void main(String args[]){
   
      Java8Tester java8Tester = new Java8Tester();
      Integer value1 = null;
      Integer value2 = new Integer(10);
        
      // Optional.ofNullable - 允许传递为 null 参数
      Optional<Integer> a = Optional.ofNullable(value1);
        
      // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
      Optional<Integer> b = Optional.of(value2);
      System.out.println(java8Tester.sum(a,b));
   }
    
   public Integer sum(Optional<Integer> a, Optional<Integer> b){
    
      // Optional.isPresent - 判断值是否存在
        
      System.out.println("第一个参数值存在: " + a.isPresent());
      System.out.println("第二个参数值存在: " + b.isPresent());
        
      // Optional.orElse - 如果值存在,返回它,否则返回默认值
      Integer value1 = a.orElse(new Integer(0));
        
      //Optional.get - 获取值,值需要存在
      Integer value2 = b.get();
      return value1 + value2;
   }
}

运行结果:

$ javac Java8Tester.java 
$ java Java8Tester
第一个参数值存在: false
第二个参数值存在: true
10

———— 华丽分割线 ————

好吧,上面是我在某资料网上摘录的,下面我来讲讲我在实际项目中常见用法与高级用法👇

1.最开始判断非空是: !=null 如果是集合就会加上 .size()>0

2.后面专门写了个EmptyUtils 里面两个方法 .isEmpty() .isNotEmpty()
内容:

/**
     * 判断对象是否为空
     *
     * @param obj 对象
     * @return {@code true}: 为空<br>{@code false}: 不为空
     */
    public static boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        }
        if (obj instanceof String && obj.toString().length() == 0) {
            return true;
        }
        if (obj.getClass().isArray() && Array.getLength(obj) == 0) {
            return true;
        }
        if (obj instanceof Collection && ((Collection) obj).isEmpty()) {
            return true;
        }
        if (obj instanceof Map && ((Map) obj).isEmpty()) {
            return true;
        }
        return false;
    }

    /**
     * 判断对象是否非空
     *
     * @param obj 对象
     * @return {@code true}: 非空<br>{@code false}: 空
     */
    public static boolean isNotEmpty(Object obj) {
        return !isEmpty(obj);
    }

3.再到现在,通过Optional类解决

场景一:填写出生地,省、城市、县城 必填项才能通过

        HashMap<String, String> birthplace = Maps.newHashMap();
        birthplace.put("province",null);
        birthplace.put("city",null);
        birthplace.put("county",null);

        //初级写法
        if (birthplace.get("")!=null){
            if (birthplace.get("")!=null){
                if (birthplace.get("")!=null){
                    //TODO:
                }
            }
        }

        //Optional写法
        birthplace = Optional.ofNullable(birthplace).filter(x -> {
            if (Optional.ofNullable(x.get("province")).isPresent()
                    && Optional.ofNullable(x.get("city")).isPresent()
                    && Optional.ofNullable(x.get("county")).isPresent())
                return true;
            else
                return false;
        }).get();

看到这里,就会发现无论是后期维护和拓展,Optional的写法的支持比if+else的要好,换个场景,如果是针对集合类型,if/else就会非常头痛,所以,快快使用Optional,告别空指针异常吧😀

“如何优雅的解决空指针异常——Java 8 Optional 类”的一个回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注