文章目录

  • Optional
    • 一、Optional 简介
    • 二、创建 Optional 实例
      • 2.1 empty()方法
      • 2.2 of() 方法
      • 2.3 ofNullable() 方法
    • 三、Optional的使用
      • 3.1 访问 Optional 对象的值
        • 3.1.1 get() 方法
        • 3.1.2 isPresent()方法
        • 3.1.3 ifPresent()方法
      • 3.2 返回默认值
        • 3.2.1 orElse()方法
        • 3.2.2 orElseGet()方法
        • 3.2.3 orElse() 和 orElseGet() 的不同之处
      • 3.3 返回异常
        • 3.3.1 orElseThrow()方法
      • 3.4 转换值
        • 3.4.1 map()方法
        • 3.4.2 flatMap()方法
        • 3.4.3 map()和flatMap()的区别
      • 3.5 过滤值
        • 3.5.1 filter()方法
      • 3.6 Optional 类的链式方法
    • 四、Java 9 增强
      • 4.1 or()方法
      • 4.2 ifPresentOrElse()方法
      • 4.3 stream()方法
    • 五、总结

Optional

一、Optional 简介

Opitonal是java8引入的一个新类,目的是为了解决空指针异常问题。本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。

Optional 是 Java 实现函数式编程的强劲一步,并且帮助在范式中实现。但是 Optional 的意义显然不止于此。

二、创建 Optional 实例

2.1 empty()方法

Optional<User> emptyOpt = Optional.empty();
emptyOpt.get();

尝试访问 emptyOpt 变量的值会导致 NoSuchElementException。

2.2 of() 方法

Optional<User> opt = Optional.of(user);

如果你把 null 值作为参数传递进去,of() 方法会抛出 NullPointerException

2.3 ofNullable() 方法

Optional<User> opt = Optional.ofNullable(user);

如果你把 null 值作为参数传递进去,ofNullable() 方法不会抛出 NullPointerException

因此,你应该明确对象不为 null 的时候使用 of()。如果对象即可能是 null 也可能是非 null,你就应该使用 ofNullable() 方法。

三、Optional的使用

3.1 访问 Optional 对象的值

3.1.1 get() 方法

String name = "John";
Optional<String> opt = Optional.ofNullable(name);assertEquals("John", opt.get());

这个方法会在值为 null的时候抛出异常。

3.1.2 isPresent()方法

User user = new User("john@gmail.com", "1234");
Optional<User> opt = Optional.ofNullable(user);
assertTrue(opt.isPresent());assertEquals(user.getEmail(), opt.get().getEmail());

3.1.3 ifPresent()方法

该方法除了执行检查,还接受一个Consumer(消费者) 参数,如果对象不是空的,就对执行传入的 Lambda 表达式:

opt.ifPresent( u -> assertEquals(user.getEmail(), u.getEmail()));

3.2 返回默认值

3.2.1 orElse()方法

Optional类提供了API用以返回对象值,或者在对象为空的时候返回默认值:orElse(),
如果有值则返回该值,否则返回传递给它的参数值:

User user2 = new User("anna@gmail.com", "1234");
User result = Optional.ofNullable(user).orElse(user2);assertEquals(user2.getEmail(), result.getEmail());

这里 user 对象是空的,所以返回了作为默认值的 user2。如果对象的初始值不是 null,那么默认值会被忽略。

3.2.2 orElseGet()方法

这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果:

User result = Optional.ofNullable(user).orElseGet( () -> user2);

3.2.3 orElse() 和 orElseGet() 的不同之处

  • 对象为空时两者的行为都会执行。
  • 对象不为空时,orElse()方法中的行为会执行,而orElseGet()方法中的行为不会执行。在执行较密集的调用时,比如调用 Web 服务或数据查询,这个差异会对性能产生重大影响。

3.3 返回异常

3.3.1 orElseThrow()方法

User result = Optional.ofNullable(user).orElseThrow( () -> new IllegalArgumentException());

3.4 转换值

3.4.1 map()方法

User user = new User("anna@gmail.com", "1234");
String email = Optional.ofNullable(user)
.map(u -> u.getEmail()).orElse("default@gmail.com");assertEquals(email, user.getEmail());

map() 对值应用(调用)作为参数的函数,然后将返回的值包装在 Optional 中。这就使对返回值进行链试调用的操作成为可能。

注意:如果map中操作对象为空,直接返回Optional.empty。

见源码,isPresent()先判断Optional中对象是否为null:

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

3.4.2 flatMap()方法

flatMap() 也需要函数作为参数,并对值调用这个函数,然后直接返回结果。

User user = new User("anna@gmail.com", "1234");
user.setPosition("Developer");
String position = Optional.ofNullable(user)
.flatMap(u -> u.getPosition()).orElse("default");assertEquals(position, user.getPosition().get());

注意:如果flatMap中操作对象为空,直接返回Optional.empty。 原理同上。

3.4.3 map()和flatMap()的区别

map和flatMap都接收一个mapping function参数。

map和flatMap返回的都是Optional类型的数据。

当mapping function返回的是Optional类型的数据时,可以直接使用flatMap,flatMap直接返回该Optional。

当mapping function返回的不是Optional类型的数据时,使用map,因为map会进行一次Optional的包装。

3.5 过滤值

3.5.1 filter()方法

filter() 接受一个 Predicate 参数,返回测试结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional。

User user = new User("anna@gmail.com", "1234");
Optional<User> result = Optional.ofNullable(user)
.filter(u -> u.getEmail() != null && u.getEmail().contains("@"));assertTrue(result.isPresent());

注意:如果filter中操作对象为空,直接返回自身。

见源码:

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

3.6 Optional 类的链式方法

为了更充分的使用 Optional,你可以链接组合其大部分方法,因为它们都返回相同类似的对象。

@Test
public void whenChaining_thenOk() {User user = new User("anna@gmail.com", "1234");String result = Optional.ofNullable(user).flatMap(u -> u.getAddress()).flatMap(a -> a.getCountry()).map(c -> c.getIsocode()).orElse("default");assertEquals(result, "default");
}

上面的代码可以通过方法引用进一步缩减:

String result = Optional.ofNullable(user)
.flatMap(User::getAddress)
.flatMap(Address::getCountry)
.map(Country::getIsocode)
.orElse("default");

四、Java 9 增强

Java 9 为 Optional 类添加了三个方法:or()、ifPresentOrElse() 和 stream()。

4.1 or()方法

or() 方法与 orElse() 和 orElseGet() 类似,它们都在对象为空的时候提供了替代情况。or() 的返回值是由 Supplier 参数产生的另一个 Optional 对象,可以配合flatMap使用。如果对象包含值,则 Lambda 表达式不会执行:

User result = Optional.ofNullable(user)
.or( () -> Optional.of(new User("default","1234"))).get();assertEquals(result.getEmail(), "default");

4.2 ifPresentOrElse()方法

ifPresentOrElse() 方法需要两个参数:一个 Consumer 和一个 Runnable。如果对象包含值,会执行 Consumer 的动作,否则运行 Runnable。

如果你想在有值的时候执行某个动作,或者只是跟踪是否定义了某个值,那么这个方法非常有用:

Optional.ofNullable(user).ifPresentOrElse( u -> logger.info("User is:" + u.getEmail()),
() -> logger.info("User not found"));

4.3 stream()方法

它通过把实例转换为 Stream 对象,让你从广大的 Stream API 中受益。如果没有值,它会得到空的 Stream;有值的情况下,Stream 则会包含单一值。

User user = new User("john@gmail.com", "1234");
List<String> emails = Optional.ofNullable(user)
.stream()
.filter(u -> u.getEmail() != null && u.getEmail().contains("@"))
.map( u -> u.getEmail())
.collect(Collectors.toList());assertTrue(emails.size() == 1);
assertEquals(emails.get(0), user.getEmail());

五、总结

Optional 是 Java 语言的有益补充 —— 它旨在减少代码中的 NullPointerExceptions,虽然还不能完全消除这些异常。

它也是精心设计,自然融入 Java 8 函数式支持的功能。

总的来说,这个简单而强大的类有助于创建简单、可读性更强、比对应程序错误更少的程序。

Java Optional使用相关推荐

  1. java Optional操作

    目录 Optional对象的创建 isPresent()和isEmpty()判空处理 ifPresent()和ifPresentOrElse()的条件动作 Optional对象中获取值 orElse( ...

  2. Java Optional容器判空处理

    Java Optional容器判空处理 1. Java判空概述 2. Java判空方式 2.1 普通判空方式 2.2 Optional判空方式 1. Java判空概述 Java判空方式有很多多,可以i ...

  3. JAVA中throw用法例子,Java Optional orElseThrow()用法及代码示例

    Java中的java.util.Optional类的orElseThrow()方法用于获取此Optional实例(如果存在)的值.如果此Optional实例中不存在任何值,则此方法将引发从指定供应商生 ...

  4. java optional 用法_Java 8中的Optional: 如何正确使用?

    Java 8中出现一个新的Optional类型,和其他语言中null的替代品类似. 本文将讨论如何使用这种新类型,即它的主要用例是什么. 什么是Optional类型? Optional是对单个对象包装 ...

  5. Java Optional学习笔记

    (1) 这个Optional.of方法还是不接收null作为输入参数: 而Optional.ofNullable可以接收null参数: isPresent判断有无数据,这个没啥可以说的: 如果Opti ...

  6. java optional用法_2019年 Java 调查报告:“被取代”是不存在的!

    作者 | Nikos Vaggalis 译者 | 冬雨 策划 | 田晓旭 尽管 Java 被称为编程语言的"老马",但它仍在不断发展. 在 Tiobe 排行榜中,它仍然是的第一名, ...

  7. Java Optional的使用实践概述

    题记:不到最后时刻,千万别轻言放弃,无论结局成功与否,只要你拼博过,尽力过,一切问心无愧 Java 8是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具 ...

  8. 看我发现了什么好东西? Java Optional,绝对值得一学 | 原力计划

    作者 | 沉默王二 来源 | CSDN博客 头图 | 付费下载自视觉中国 出品 | CSDN(ID:CSDNnews) 想学习,永远都不晚,尤其是针对 Java 8 里面的好东西,Optional 就 ...

  9. java optional 用法_理解、学习与使用Java中的Optional

    从Java8 引入的一个很有趣的特性是Optional类.Optional类主要解决的问题是臭名昭著的空指针异常(NullPointerException) -- 每个 Java 程序员都非常了解的异 ...

  10. java optional详解_Java 8 中的 Optional 使用详解

    1 概述Optional 的完整路径是 java.util.Optional,使用它是为了避免代码中的 if (obj != null) { } 这样范式的代码,可以采用链式编程的风格 而且通过 Op ...

最新文章

  1. python减少内存_如何降低 Python 的内存消耗量?
  2. 人工智能和区块链的融合
  3. 水系图一般在哪里找得到_一款支持智能抠图、钢笔抠图的在线抠图工具上线了 速抠图 sukoutu.com...
  4. 程序员的数学笔记3--迭代法
  5. windows10系统的电脑如何设置密码?
  6. Springboot03整合SpringDataJPA访问MySQL数据库
  7. 一个3200位长的tcp报文传到ip层_运输层
  8. eclipse-indigo 中 user libraries 自动部署 WEB-INF/lib 配置
  9. NSJSONSerialization-JSON数据与NSDictionary和NSArray之间的转化
  10. PID控制算法的C语言实现
  11. 网上赚钱的方法门路有哪些?盘点网上赚钱最可靠的10种方法!
  12. docx文档怎么排列图片_腾讯、石墨、金山在线文档简单对比
  13. java 冒泡_Java中的冒泡排序
  14. 思科路由器及交换机基本配置
  15. wireshark常用筛选命令
  16. php 随机字符串函数,PHP 生成随机字符串的方法函数
  17. GitHub开源项目地址
  18. PHP伪造IP或来源地址
  19. 教程 2 || 10分钟成为简笔画达人,然后......
  20. 【项目问题总结】4:修改操作的重复性验证逻辑

热门文章

  1. 整理最新境外投资企业(机构)备案结果公开名录
  2. com.android.frameworks.telresources,Android 8.1 MTK6739修改文档
  3. Python企业微信群机器人推送消息,定时提醒。
  4. 麓言信息专业ui设计
  5. 蓝桥杯 算法训练 自行车停放(Java)
  6. Godot3游戏引擎入门之十二:Godot碰撞理论以及KinematicBody2D的两个方法
  7. 云原生 - 工作流引擎 Zeebe
  8. 股市投资必修课十三–--会买的才是师傅
  9. SE16N修改SAP标准表内容
  10. 华硕rog枪神5和魔霸5有什么区别 哪个好详细性能配置对比