使用Optional处理null
Java 8引入了一个Optional类,用来解决空指针异常(NullPointerException)。刚开始使用的时候看到ifPresent()
,isPresent()
和get()
这些函数,感觉和直接通过比较null
值的方式差别不大,纯属脱了裤子放屁。可是后来看到一些最佳实践的代码例子,才发觉是之前肤浅了,没有理解到Optional的正确的打开方式,所以在这里记录一下。
一个例子
使用Optional之前
如果一个类中嵌套了很多层的对象,那么为了访问最里层的嵌套对象,不得不写出下面这种很繁琐的代码。
1 | if (user != null) { |
使用Optional后
如果使用Optional的话,只需要一行代码就可以搞定。
1 | String isocode = Optional.ofNullable(user) |
最佳实践
Optional 是用来作为方法返回值的
Optional 是为了清晰地表达返回值中没有结果的可能性,且如果直接返回 null 很可能导致调用端产生错误(尤其是NullPointerException)。通常用来作为方法返回值,不建议用着方法参数。
1 | // 创建一个可能为空的 Optional 对象 |
使用orElse(),orElseGet(),orElseThrow()取值
- T orElse(T other): 如果值存在返回,否则返回orElse中传入的other
- T orElseGet(Supplier<? extends T> other) :如果存在则返回该值,否则调用other这个函数编程并返回该调用的结果
- T orElseThrow(Supplier<? extends X> exceptionSupplier): 如果存在则返回该值,否则为空的话可以抛出自定义的异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14Optional<String> name = Optional.ofNullable(null);
// 使用 orElse(T other)
String greeting = "Hello, " + name.orElse("Guest"); //如果 Optional 对象包含一个非空的值,返回该值,否则返回给定的默认值
System.out.println(greeting); // 输出:Hello Guest
// 使用 orElseGet(Supplier<? extends T> supplier)
greeting = "Hello, " + name.orElseGet(() -> "Guset");//如果 Optional 对象包含一个非空的值,返回该值,否则返回由给定的供应者操作生成的值
System.out.println(greeting); // 输出:Hello Guset
// 使用 orElseThrow(Supplier<? extends X> exceptionSupplier)
greeting = "Hello, " + name.orElseThrow(() -> new NullPointerException("null"));//如果 Optional 对象包含一个非空的值,返回该值,否则抛出由给定的异常供应者操作生成的异常
// 抛出 java.lang.NullPointerException: null 异常orElseGet和orElse的区别?
当 ofNullable() 传入参数不为空时,orElse() 方法仍然创建了 other这个 对象,而orElseGet() 方法不创建对象。在执行较密集的调用时,这个差异会对性能产生重大影响
使用map()和filter()函数做转换
- Optional filter(Predicate<? super T> predicate): 对Optional中的value进行过滤,如果不匹配,返回空
- Optional map(Function<? super T, ? extends U> mapper): 对Optional中的value进行转换映射为另外一个对象,如果value为空,返回empty Optional
- Optional flatMap(Function<? super T, Optional> mapper): 接受一个返回值为Optional的映射函数参数,该返回值亦是flatMap方法的返回值若结果为空,则返回 空Optional
1
2
3
4
5
6
7
8
9Optional<String> name = Optional.ofNullable("John");
// 使用 map(Function<? super T,? extends U> mapper)
String greeting = "Hello, " + name.map(s -> s.toUpperCase()).get();//如果 Optional 对象包含一个非空的值,对该值应用给定的映射函数,返回一个包含映射结果的 Optional 对象,否则返回一个空的 Optional 对象
System.out.println(greeting); // 输出:Hello JOHN
// filter(Predicate<? super T> predicate)
greeting = "Hello " + name.filter(s -> !s.isEmpty()).get();//如果 Optional 对象包含一个非空的值,并且该值满足给定的谓词条件,返回包含该值的 Optional 对象,否则返回一个空的 Optional 对象
System.out.println(greeting); // 输出:Hello john
参考资料
- 标题: 使用Optional处理null
- 作者: zjun
- 创建于 : 2018-08-03 23:01:12
- 更新于 : 2023-12-01 16:54:07
- 链接: https://zjun.site/2018/08/d239c27ca7d9.html
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论