java8 系列 -05 Optional

本贴最后更新于 1875 天前,其中的信息可能已经时异事殊

空指针异常我想是程序员见到比较多的异常啦,今天来探索的这个 Optional 工具类就是来处理这类问题的。用过 Google Guava(后期应该会出一个系列,请持续关注)的都应该知道,Guava 这套工具类库里面也有一个 Optional,而且作用和今天来探索的这个 java 新特性是一样的。既然又是探索,那我们先打开 idea,然后 ctrl+ 鼠标左键进到 optional 的世界看一下吧。

源码片段

接下来我将逐行解释一下源码(像我这样给 jdk 源码这样加注释的怕是很少了 ^_^)

// final修饰说明此类是无法被引用的哈
public final class Optional<T> {
    // 这个是EMPTY的实例
    private static final Optional<?> EMPTY = new Optional<>();

    // 如果非空,则为该值;如果为空,则表示不存在任何值。
    private final T value;

    // 构造私有看来此类也不能被new
    private Optional() {
        this.value = null;
    }

    // 返回一个空的实例,@SuppressWarnings不提醒警告
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

    // 根据value来构造出一个实例
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

    // 返回一个带有value的optional,注意value如果为空则会报空指针异常
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    // 和上面一样,但是这里value为空不会有空指针异常
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

    // 如果当前有值则返回当前值,否则抛出NoSuchElementException
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

    // 如果这个Optional是存在的则返回true,否则为false
    public boolean isPresent() {
        return value != null;
    }

    // 如果option对象保存的值不是null,则调用consumer对象,否则不调用
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

    // 判断Optional对象中保存的值是否满足Predicate,并返回新的Optional。
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

    // 如果value不为null,则进行函数运算,返回一个新的Optional,否则返回empty
    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));
        }
    }

    // 上一章讲到过Stream里面的flatMap,就是对一个大的集合进行一个扁平化的操作。
    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
    }

    // 不解释
    public T orElse(T other) {
        return value != null ? value : other;
    }

    // 怎么办?也不想解释,关于Supplier供给者函数式的作用麻烦翻到此系列的第二章
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

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

    // 重写了Object的方法
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof Optional)) {
            return false;
        }

        Optional<?> other = (Optional<?>) obj;
        return Objects.equals(value, other.value);
    }

    // 重写了Object的方法
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }

    // 如果值不为空则返回Optional[value],否则Optional.empty。认真看过我上一章的也许还能记忆起来
    @Override
    public String toString() {
        return value != null
            ? String.format("Optional[%s]", value)
            : "Optional.empty";
    }
}

优雅食用

这里捡几个比较常用的在这里列出来吧

of && ofNullable

上面注释有提到,这两个都是被用来创建 Optional 对象。区别在于 ofNullable 还判空了。这就造成了 ofNullable 的实用性比 of 要高那么一丢丢。下面来看一个例子吧~

public class OptionalDemo {
    public static void main(String[] args) {
        Optional<String> ofNullable = Optional.ofNullable(null);
        System.out.println(ofNullable);// Optional.empty

        Optional<String> of = Optional.of(null); // 代码执行到这里会抛出NullPointerException
    }
}

isPresent

isPresent 有两种作用:一个是判断是否有值,还有一个返回的是 void,如果不为空的话执行 Consumer 消费型函数式代码。

public class OptionalDemo {
    public static void main(String[] args) {
        // 先创建一个Optional
        Optional<String> val = Optional.ofNullable("yes");
        System.out.println(val.isPresent()); // true

        val.ifPresent(s -> System.out.println(s.concat(" or no?"))); // yes or no?
    }
}

filter && map

直接看例子最好啦

public class OptionalDemo {
    public static void main(String[] args) {
        Optional<String> optional = Optional.ofNullable("code666");
        Optional<String> newOptional = optional.map(param->param.concat(".top"));
        System.out.println(newOptional); // Optional[code666.top]

        Optional filterOptional = optional.filter(param->param.contentEquals("Sean")); // 如果条件成立的话会返回Optional[code666]
        System.out.println(filterOptional); // Optional.empty
    }
}

orElse && orElseGet

长得虽然差不多,orElseGet 还带了一个 Supplier 供给者函数看着高大上一点,其实也差不多。记得在第二章有说过,供给者函数就有点像工厂的味道而已。

public class OptionalDemo {
    public static void main(String[] args) {
        String res = (String) Optional.ofNullable(null).orElse("这个结果为空");
        System.out.println(res); // 这个结果为空

        String res2 = (String) Optional.ofNullable(null).orElseGet(()-> "The result is empty.");
        System.out.println(res2); // The result is empty.
    }
}
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖
  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    161 引用 • 473 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 511 关注
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 604 关注
  • 阿里云

    阿里云是阿里巴巴集团旗下公司,是全球领先的云计算及人工智能科技公司。提供云服务器、云数据库、云安全等云计算服务,以及大数据、人工智能服务、精准定制基于场景的行业解决方案。

    89 引用 • 345 回帖
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    123 引用 • 168 回帖
  • 自由行
    1 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    19 引用 • 23 回帖 • 685 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    53 引用 • 85 回帖
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    492 引用 • 1383 回帖 • 375 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    675 引用 • 535 回帖
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    116 引用 • 99 回帖 • 268 关注
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    5 引用 • 15 回帖 • 221 关注
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 1 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 549 关注
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    34 引用 • 37 回帖 • 498 关注
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 370 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • WebClipper

    Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。

    3 引用 • 9 回帖 • 6 关注
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    76 引用 • 390 回帖
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 439 关注
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    164 引用 • 594 回帖 • 1 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    18709 引用 • 69853 回帖 • 1 关注
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 685 关注
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    34 引用 • 467 回帖 • 693 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 7 关注
  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    533 引用 • 3528 回帖