作为程序员,你肯定遇到过NullPointerException, 这个异常对于初出茅庐的新人, 还是久经江湖的老手都是不可避免的痛, 可又是那么的无能为力,为了解决它,你只能在使用某个值之前,对其进行判空处理。然而这样会使得代码变得臃肿不堪。幸好jdk8引入了optional来处理了null的问题,使得我们可以不再对null做过多的关心。

先展示jdk8之前的写法

 // First before jdk8
Long id = 0L;
User user = getUserById(id);
if (user != null) {
String name = user.getName();
System.out.println("name=" + name);
}

如果不对方法拿到的user 进行空判断,下面获取其属性很容易就会出现空指针异常。

jdk 8 写法

 User userById = Optional.ofNullable(getUserById(id)).orElse(new User());
String name = userById.getName();
System.out.println("new name=" + name);

这种写法就避免了空的判断,代码显得很简便

下面介绍下 optional 的方法

1、首先是构造  of,  ofNullable, empty

 // empty 构建空的optional对象
Optional<Object> empty = Optional.empty(); // of 构造user的optional 对象,user对象不为空, 如果为空,构建的时候就会报nullPointerException
User user = new User();
Optional<User> userOptional = Optional.of(user); // ofNull 构造optional对象,内部user如果为空,就构建空的optional对象
Optional<User> userOptionalOfNull = Optional.ofNullable(user); Optional<Object> objectOptional = Optional.of(null);
System.out.println(objectOptional); Exception in thread "main" java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.<init>(Optional.java:96)
at java.util.Optional.of(Optional.java:108)
at com.zbb.jdk.jdk8Test.optional.OptionalOfTest.main(OptionalOfTest.java:32)

看下ofNullable 方法源码

2、 获取 ifPresent, get, isPresent

 Optional<User> userOptional = Optional.ofNullable(getUserById(id));
// isPresent 判断optional对象是否存在,如果存在,返回true, 否则返回false
if(userOptional.isPresent()){
// 已判断存在
// get 如果创建的Optional中有值存在,则返回此值,否则抛出NoSuchElementException
User user = userOptional.get();
System.out.println("name" + user.getName());
} // 创建的Optional中的值存在,则执行该方法的调用,否则什么也不做
// ifPresent方法的参数是一个函数式接口, 该方法无返回值,可以直接用lambda表达式
userOptional.ifPresent(user -> System.out.println("name=" + user.getName()));

最开始的例子也可以用isPresent来这样改,但是这样和原先判空并没有什么区别,只是方法不同而已,本质没区别,所以不推荐。看下这几个方法的源码

3、获取 orElse, orElseGet, orElseThrow

 Optional<User> userOptional = Optional.ofNullable(getUserById(id));

 //orElse 如果optional 有值就返回值,如果没有就返回一个默认值
// 默认值就是我们创建的一个类
User user = userOptional.orElse(new User("xiaohong", "123456789"));
System.out.println("name=" + user.getName()); // name=xiaohong //orElseGet 如果optional有值就返回值,如果没有,就执行一个Supplier接口,返回生成的值
User userOrElseGet = userOptional.orElseGet(() -> new User("xiaohongGet", "123456789"));
System.out.println("name=" + userOrElseGet.getName()); //name=xiaohongGet //orElseThrow 如果optional有值就返回值,如果没有,就返回一个指定的Supplier接口生成的异常
User userElseThrow = userOptional.orElseThrow(() -> new Exception("userOptional 为空!")); // 为空时,抛出的异常
Exception in thread "main" java.lang.Exception: userOptional 为空!
at com.zbb.jdk.jdk8Test.optional.OptionalOrElse.lambda$main$1(OptionalOrElse.java:29)
at java.util.Optional.orElseThrow(Optional.java:290)
at com.zbb.jdk.jdk8Test.optional.OptionalOrElse.main(OptionalOrElse.java:29)

看下源码

orElseThrow 同理

4、过滤  filter

 Optional<User> userOptional = Optional.ofNullable(new User("xiao", "123456"));

 //optional中的值符合条件,则返回该optional对象,否则返回空的optional对象
User user = userOptional.filter(u -> NAME.equals(u.getName())).orElse(new User("不满足", ""));
System.out.println("name=" + user.getName()); //name=xiao

5、转化  map, flatMap

 Optional<String> optional = Optional.ofNullable("zhang,san");

 //map  optional对象存在就执行Funciton函数
// 可以返回任意类型的值
// 该函数式接口对optional对象中的值进行修改,返回修改后的值
Optional<String[]> optionalMap = optional.map(s -> s.split(",")); //Optional[[Ljava.lang.String;@19dfb72a] // flatMap方法中的lambda表达式返回值必须是Optionl实例
Optional<String> optionalFlatMap = optional.flatMap(s -> Optional.of("lisi"));//Optional[lisi]

看源码知道,map 和 flatmap 都是如果optional中的值存在,就对该值执行提供的Function函数调用,返回一个optional类型的值,否 
则就返回一个空的optional对象。

最大的区别是map 函数执行之后是任意的类型数据,调用结束map 会再用optional对结果进行包装,而flatmap 是执行完之后就是一个optional 实例 ,flatmap 不会对结果进行optional封装。

JDK8,Optional的更多相关文章

  1. VB几种函数参数传递方法,Variant,数组,Optional,ParamArray

    VB几种函数参数传递方法,Variant,数组,Optional,ParamArray 一) 过程的参数被缺省为具有 Variant 数据类型. 1)ByRef按 地址传递参数在 VB 中是缺省的 按 ...

  2. 环境变量配置为jdk8,显示的java版本为jdk7

    经查找发现是jdk版本的问题,我系统环境变量配置的是jdk7,可是这个war包需要在jdk8的环境下运行.于是我就手动将环境变量的jdk7换成jdk8,结果发现依然还是会出现以上问题.于是我打开cmd ...

  3. win10怎么安装JDK8,配置JDK8的环境变量

    win10怎么安装JDK8,配置JDK8的环境变量 本文详细说明怎么在win10上安装JDK8,方便小伙伴们快速学会安装与配置JDK. 工具/原料 windows10 jdk-8u51-windows ...

  4. swift中,Optional、?与!之间的关系

    swift中,Optional.?与!之间的关系 Optional <ClassName> 与 ClassName? 等价 对 ClassName! 强制取值会导致崩溃(如果对象为nil时 ...

  5. Linux在线安装jdk8,并配置环境变量

    1.创建相关目录:下载目录.安装目录 下载目录: cd / 2.下载jdk8到目录 下载前先跳转到下载目录,比如希望最后压缩包下载到/home/bak/下, 则先创建bak目录,命令如下: 注意:如果 ...

  6. 大忙人的jdk8,比出生晚了好几个激情的夏天

    写给大忙人的jdk8到手了,第一件事情就蒙蔽了,mac装的jdk7,切换jdk的功能要整出来才行,下好jdk8up101安装,假装几行代码搞定目标在命令行下,可以通过命令'jdk6', 'jdk7', ...

  7. java8:(Lambda 表达式,Supplier,@FunctionalInterface,foreach(),Optional,Stream().collect,双冒号,joining,partitioningBy分区,collectingAndThen,filter())

    1.Lambda 表达式: 引导:http://www.cnblogs.com/yulinfeng/p/8452379.html DEMO1: List<String> names1 = ...

  8. java 11 增加了一系列的字符串处理方法,Optional 加强 ,改进的文件API

    增加了一系列的字符串处理方法 如以下所示. // 判断字符串是否为空白 " ".isBlank(); // true // 去除首尾空白 " Javastack &quo ...

  9. 升级到JDK8,编译时发生 Error:java: java.lang.ExceptionInInitializerError

    编译的时候出现这个问题.使用1.7的jdk没问题,但是由于po主的项目中,使用了java8编写的代码,解决java8兼容问题成为解决这个问题的首选方案. 这个日志太过简单,只告知一个异常信息,这个异常 ...

随机推荐

  1. 移动前端不得不了解的HTML5 head 头标签 —— link 标签

    目录 link 标签 rss订阅 不推荐的link标签 favicon 图标 link 标签 说到 link 标签,估计大家的第一反应和我一样,就是引入外部CSS样式文件的,不错,这是 link 标签 ...

  2. 如何正确的探索 Microsoft Ignite The Tour

    Microsoft Ignite The Tour 是一年一度微软为全球开发者.IT专家.安全专家以及数据专家提供的为期两天,包含众多核心产品的实践性技术培训.2019.12.10-2019.12.1 ...

  3. usb工业相机之硬件设计-双缓冲-双端口sdram-fpga

    usb工业相机之硬件设计-双缓冲-双端口sdram-fpga 在前期的产品设计中,采用cb提供的结构,68013直接操作摄像头,iic配置摄像头寄存器,板载晶振提供时钟,摄像头的pclk直接接ifcl ...

  4. 使用java语言实现八皇后问题

    八皇后问题,在一个8X8的棋盘中,放置八个棋子,每个棋子的上下左右,左上左下,右上右下方向上不得有其他棋子.正确答案为92中,接下来用java语言实现. 解: package eightQuen; / ...

  5. Django 09

    目录 多对多三种创建方式 全自动 纯手撸 半自动(推荐) form组件 校验数据 渲染标签 展示错误信息 validators校验器 钩子函数 补充 多对多三种创建方式 全自动 ManyToManyF ...

  6. 【CSS】309- 复习 CSS盒模型

    点击上方"前端自习课"关注,学习起来~ 一.概念 CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:外边距(margin).边框(border).内边距(padding ...

  7. ruby on rails测试

    Rspec测试 Rspec(基本测试) 安装 group :development, :test do gem 'rspec-rails', '~> 3.5' end rails generat ...

  8. Callable接口实现线程

    public class CallableDemo { public static void main(String[] args) throws Exception, ExecutionExcept ...

  9. CSS | 自适应两栏布局方法

    html代码: <div class="main"> <div class="left" style="background: #0 ...

  10. spring源码学习(三)--spring循环引用源码学习

    在spring中,是支持单实例bean的循环引用(循环依赖)的,循环依赖,简单而言,就是A类中注入了B类,B类中注入了A类,首先贴出我的代码示例 @Component public class Add ...