作为程序员,你肯定遇到过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封装。

最新文章

  1. Linux.NET学习手记(7)
  2. Cordova webapp实战开发:(7)如何通过简单的方法做到,不重新发布APP来修复bug、增加功能、或者躲开苹果的一些严格审核?
  3. clearInterval,setInterval,clearTimeout,setTimeout
  4. Java动态代理一Proxy
  5. 如何获取checkboxlist的多个选中项
  6. 一些android系统参数的获取
  7. Xcode7 制作通用的framework(转)
  8. Type mytableview does not confirm to portocol UITableViewDataResource
  9. 全文索引--自定义chinese_lexer词典
  10. 前端小白的gulp入门
  11. Codeforces Round #542 C. Connect 搜索
  12. 10 python 初学(Python 的编码解码)
  13. mysql连接拍错总结
  14. Hadoop开发环境配置2-eclipse集成maven插件
  15. 截图软件FastStone
  16. [二叉树建树]1119. Pre- and Post-order Traversals (30) (前序和后序遍历建立二叉树)
  17. Android之SurfaceView使用总结
  18. LaTeX绘图宏包 Pgfplots package
  19. c语言URL通过Http下载mp3 格式
  20. 浅谈前端与SEO

热门文章

  1. hibernate查询方式(四)
  2. (全国多校重现赛一)D Dying light
  3. C.Dominated Subarray
  4. linux-history、find、
  5. 大数据学习笔记——Java篇之IO
  6. webpack学习_webpack-dev-server自动编译代码
  7. 《Java基础知识》Java多态对象的类型转换
  8. Python之利用Whoosh搭建轻量级搜索
  9. MySql数据库之连接查询
  10. AE单词备忘