Java8特性之Optional
保留所有版权,请引用而不是转载本文(原文地址 https://yeecode.top/blog/16/ )。
1 概述
Java 8由Oracle公司于2014年3月18日发布,至今已过去数年之久。然而,直到今日仍有许多软件开发者对其相关特性不了解,这可能主要是Java教材更新缓慢的原因。为了使大家对与Java8的特性有全面系统的了解,本公众号将连续几篇文章介绍Java8中的各个特性。
Java8中新增的特性主要有:
- Lambda 表达式 − Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。
- 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
- 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
- 新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
- Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
- Date Time API − 加强对日期与时间的处理。
- Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
- Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。
本文介绍其中的Optional类。其它特性会在后续文章中陆续介绍。
2 Optional类
到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。
Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
常用函数:
- of:为非null的值创建一个Optional。of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException。因此不经常用。
- ofNullable:为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。
- isPresent:如果值存在返回true,否则返回false。
- ifPresent:如果Optional实例有值则为其调用consumer,否则不做处理
- get:如果Optional有值则将其返回,否则抛出NoSuchElementException。因此也不经常用。
- orElse:如果有值则将其返回,否则返回指定的其它值。
- orElseGet:orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值
- orElseThrow:如果有值则将其返回,否则抛出supplier接口创建的异常。
- filter:如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。
- map:如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。
- flatMap:如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。
使用Optional,我们就可以把下面这样的代码进行改写。
public static String getName(User u) {
if (u == null)
return "Unknown";
return u.name;
}
不过,千万不要改写成这副样子。
public static String getName(User u) {
Optional<User> user = Optional.ofNullable(u);
if (!user.isPresent())
return "Unknown";
return user.get().name;
}
这样改写非但不简洁,而且其操作还是和第一段代码一样。无非就是用isPresent方法来替代u==null。这样的改写并不是Optional正确的用法,我们再来改写一次。
public static String getName(User u) {
return Optional.ofNullable(u)
.map(user->user.name)
.orElse("Unknown");
}
这样才是正确使用Optional的姿势。那么按照这种思路,我们可以安心的进行链式调用,而不是一层层判断了。
使用举例:
public class TestBean {
public static void main(String[] args) {
String nullString = null;
Optional<String> optionalS1 = Optional.ofNullable(nullString);
String normalString = "HelloWorld";
Optional<String> optionalS2 = Optional.ofNullable(normalString);
System.out.println("s1:" + optionalS1.orElse("None value fund!"));
System.out.println("s2:" + optionalS2.orElse("None value fund!"));
System.out.println("---");
System.out.println(
optionalS1
.map(a -> {System.out.print("do map... ");return a.concat("+++");})
.orElse("None value!")
);
System.out.println(
optionalS2
.map(a -> {System.out.print("do map... ");return a.concat("+++");})
.orElse("None value!")
);
}
}
运行结果:
s1:None value fund!
s2:HelloWorld
---
None value!
has value. HelloWorld+++
3 总结
Java8 提供的Optional类使得Java程序更为健壮,防止代码受到空值的污染。
关于Java8中Optional类的介绍就到这里,至此,通过前面的几篇文章和本文,我们对Java8中的特性进行了较为全面的介绍。希望大家在后续的编码中能使用这些特性,编写更加健壮和易读的代码。
可以访问个人知乎阅读更多文章:易哥(https://www.zhihu.com/people/yeecode),欢迎关注。