首页 > 其他分享 >Optional:判空新姿势

Optional:判空新姿势

时间:2022-10-11 10:56:57浏览次数:44  
标签:姿势 Function return value 判空 null Optional public

1、NPE 问题

NPE(Null Pointer Exception):空指针异常。

示例:对象 User 引用对象 Info

  1. 错误写法:无法保证非空,可能导致 NPE。

    String infoId = user.getInfo().getId();
    
  2. 正确写法:进行 if 判断,但代码臃肿。

    if (user != null) {
        Info info = user.getInfo();
        if (info != null) {
            String InfoId = info.getId();
        }
    }
    

2、Optional API

Optional:一个存储 value 的容器(package java.util)

value 代表真实值(可能空/非空),一旦设置无法修改。

2.1、成员变量

final 修饰

  • EMPTY:代表空对象实例。

  • value:代表 Optional 中的真实值。

    private static final Optional<?> EMPTY = new Optional<>();
    
    private final T value;
    

2.2、创建 Optional

2.2.1、构造方法

private 权限,无法直接访问。

  • Optional():创建空值实例。

  • Optional(T value):创建非空值实例(空则 NPE)。

    private Optional() {
        this.value = null;
    }
    
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }
    
    // 相关代码:空值则抛 NPE
    public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }
    

2.2.2、创建方法

public 权限,提供对构造器的访问。

  • of(T value):value 必须非空,否则 NPE。

  • ofNullable(T value):允许 value 为空。

  • empty():返回 EMPTY 实例。

    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;
    }
    

2.3、取值

2.3.1、纯取值

get():若 value 空则抛异常

public T get() {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}

2.3.2、默认值

若 value 空则给定默认值

类似 map.getOrDefault(key, defaultVal)

  • orElse(T other):给定 value 类型值。

  • orElseGet(Supplier):给定 Supplier 的输出结果。

    public T orElse(T other) {
        return value != null ? value : other;
    }
    
    public T orElseGet(Supplier<? extends T> supplier) {
        return value != null ? value : supplier.get();
    }
    

2.3.3、异常

  • orElseThrow():同 get(),抛 NoSuchElementException 类型。

  • orElseThrow(Supplier):指定异常类型。

    public T orElseThrow() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }
    
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }
    

case

  • 示例

    User user = ?;
    Optional<User> u = Optional.ofNullable(user);
    
  • 执行不同方法

    User 非空 User 空
    u.get() 返回 user 实例 抛 NoSuchElementException 类型
    u.orElse(createUser()) 同上 返回 createUser() 方法结果
    u.orElseGet(() -> createUser()) 同上 返回 Supplier 执行结果,即 createUser() 方法
    u.orElseThrow() 同上 抛 NoSuchElementException 类型
    u.orElseThrow(() -> new RuntimeException("用户不存在")) 同上 抛指定异常类型

2.4、流式编程

2.4.1、流

stream()

public Stream<T> stream() {
    if (!isPresent()) {
        return Stream.empty();
    } else {
        return Stream.of(value);
    }
}

2.4.2、映射

xxxMap(Function):将当前 Optional 实例转换成另一个 Optional。

流程:先校验 Function 非空,再根据 value 不同情况进行操作。

  • :返回 EMPTY 实例。
  • 非空:返回 Function 的执行结果。

相关 API

  • map(Function):允许 Function 结果为空。

  • flatMap(Function):不允许 Function 结果为空。

    public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent()) {
            return empty();
        } else {
            // 允许空
            return Optional.ofNullable(mapper.apply(value));
        }
    }
    
    public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent()) {
            return empty();
        } else {
            // 不允许空
            @SuppressWarnings("unchecked")
            Optional<U> r = (Optional<U>) mapper.apply(value);
            return Objects.requireNonNull(r);
        }
    }
    

2.4.3、过滤

filter(Predicate):检验当前 Optional 是否满足条件,是则保留,否则过滤。

流程:先校验 Predicate 非空,再根据 value 不同情况进行操作。

  • :返回 Optional 半身。
  • 非空:执行 Predicate,当前 Optional 满足条件则返回,否则返回 EMPTY 实例。

API

public Optional<T> filter(Predicate<? super T> predicate) {
    Objects.requireNonNull(predicate);
    if (!isPresent()) {
        return this;
    } else {
        return predicate.test(value) ? this : empty();
    }
}

示例

// 参数表示年龄
User user1 = new User(17);
User user2 = new User(19);

Optional<User> u1 = Optional.of(user1);
Optional<User> u2 = Optional.of(user2);

// 返回 u1
Optional<User> res1 = u1.filter(u -> u.getAge() < 18);
// 返回 EMPTY
Optional<User> res2 = u2.filter(u -> u.getAge() < 18);

2.5、判空

  • 判空:isPresent(),isEmpty()

    public boolean isPresent() {
        return value != null;
    }
    
    public boolean isEmpty() {
        return value == null;
    }
    
  • 判断并操作

    • ifPresent(Consumer):判断 value 非空时执行 Consumer 动作。

    • ifPresentOrElse(Consumer):value 非空时同上,value 空时执行 Runnable 方法。

      public void ifPresent(Consumer<? super T> action) {
          if (value != null) {
              action.accept(value);
          }
      }
      
      public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) {
          if (value != null) {
              action.accept(value);
          } else {
              emptyAction.run();
          }
      }
      

标签:姿势,Function,return,value,判空,null,Optional,public
From: https://www.cnblogs.com/secretmrj/p/16778470.html

相关文章

  • Redis实现分布式锁的7种方案,及正确使用姿势!
    Redis实现分布式锁的7种方案,及正确使用姿势!种方案前言日常开发中,秒杀下单、抢红包等等业务场景,都需要用到分布式锁。而Redis非常适合作为分布式锁使用。本文将分七个......
  • 恶意代码分析实战 隐蔽的恶意代码启动 lab12-1 12-2 12-3 各种进程注入的姿势都在这里
    一、常用的隐藏技术启动器进程注入进程替换Hook注入DetoursAPC注入二、Lab12-11.行为分析执行之后的效果是每隔一段时间会弹窗。查看processmomitor。可以......
  • 多人协作多版本开发冲突的正确解决姿势
    这里实际上用上一个关键命令:​​gitmerge--no-ff分支名​​​​注意:无论何种情况,都绝不允许把开发、测试、预生产的代码拉到自己分支上解决冲突,因为上面有很多垃圾代码。......
  • 还用 !=null 判空?试试 Java 8 的全新写法吧!
    1.API介绍1、Optional(Tvalue),empty(),of(Tvalue),ofNullable(Tvalue)这四个函数之间具有相关性,因此放在一组进行记忆。先说明一下,Optional(Tvalue),即构造函数,它是......
  • 搜索 .empty 判空
    搜索.empty判空搜索 .pop_back出栈 控制流输出格式的函数 iomanip搜索.back返回栈顶元素for_each算法find算法sort算法 容器vectorlistsetmap控制......
  • Optional 常用方法总结
    转载请注明出处:Optional类是JAVA8提供的判断程序是否为空提供的包装工具类;可以减少代码中的是否为空的判断,以及减少NullPointerExceptions;使得程序变得更为健壮......
  • 使用process.env.NODE_ENV的正确姿势
    什么是process.env.NODE_ENVprocess.env.NODE_ENV应该是我们最熟悉的环境变量了,它经常出现在使用框架或者类库的时候,被用来区分不同的环境(开发,测试,生产等),以便我们进行相......
  • Longhorn 的正确使用姿势:如何处理增量 replica 与其中的 snapshot/backup
    作者简介吴硕,SUSESeniorSoftwareDevelopmentEngineer,已为Longhorn项目工作近四年,是项目maintainer之一。本文将介绍Longhorn的基本功能和架构,replica和backup......
  • Optional源码解析与实践
    1导读NullPointerException在开发过程中经常遇到,稍有不慎小BUG就出现了,如果避免这个问题呢,Optional就是专门解决这个问题的类,那么Optional如何使用呢?让我们一起探索一下......
  • Optional使用
     importjava.util.HashMap;importjava.util.Map;//最外层对象publicclassOuter{Nestednested;NestedgetNested(){returnnested;}......