Optional简介
Optional 类是jdk8新增的一个新特性,是一个可以为null的容器对象;可以用来解决NullPointerExpection.
Optional实例化
Optional类有3个实例化的方法:
| 方法名 | 功能 |
|---|---|
| empty() | 创建一个空的Optional对象 |
| of(T t) | 创建一个包含t对象的Optional对象;t==null时,抛出NullPointerException异常 |
| ofNullable(T t) | 创建一个包含t对象的Optional对象;t==null时,创建一个空的Optional对象 |
访问Optional对象的值
| 方法名 | 功能 |
|---|---|
| get() | 如果Optional有值则将其返回,否则抛出异常 NoSuchElementException |
| orElse(T other) | 如果Optional实例有值则将其返回,否则返回orElse方法传入的参数 |
| orElseGet(Supplier<? extends T> other) | 与orElse()方法类似,但通过Supplier接口的实现用来生成默认值 |
| orElseThrow(Supplier<? extends X> eother) | 如果有值则将其返回,否则抛出supplier接口创建的异常 |
使用示例如下:
public class OptionalTest {
public static void main(String[] args) {
System.out.println("1:" + Optional.ofNullable("test").get());
System.out.println("2:" + Optional.ofNullable("test").orElse("default"));
System.out.println("3:" + Optional.ofNullable(null).orElse("default"));
System.out.println("4:" + Optional.ofNullable(null).orElseGet(() -> "default"));
// 下面两行代码分别抛出NoSuchElementException和NullPointerException
// System.out.println("5:" + Optional.empty().get());
// System.out.println("6:" + Optional.empty().orElseThrow(()->new NullPointerException()));
/**
* orElseGet/orElseThrow接受一个Supplier参数,如果对象为空,就对执行传入的 Lambda 表达式
* Supplier是一个函数式接口:无参数有返回值的Lambda表达式
* 详情参考Lambda表达式和函数式编程 ,这里不多赘述
*/
}
}
打印结果如下:
1:test
2:test
3:default
4:default
orElse 与 orElseGet区别:
当OptionAl对象不为Empty时,orElse函数依然会执行orElse的方法体,而orElseGet函数并不会执行orElseGet的方法体。
校验Optional是否为空
Optional对象为空时,操作Optional对象可能会抛出异常;校验Optional对象有两个方法:
| 方法名 | 功能 |
|---|---|
| isPresent() | Optional对象为空时返回false,否则返回true |
| ifPresent(Consumer<? super T> consumer) | 如果Optional实例有值则为其调用consumer,否则不做处理 |
public class OptionalTest {
public static void main(String[] args) {
System.out.println("1:::"+Optional.empty().isPresent());
/**
* ifPresent除了执行检查,还接受一个Consumer(消费者) 参数,如果对象不是空的,就对执行传入的 Lambda 表达式
* Consumer是一个函数式接口:有参数无返回值的Lambda表达式
*/
Optional.ofNullable("test").ifPresent((x)->System.out.println("2:::不为空:执行此Lambda表达式"));
Optional.empty().ifPresent((x)->System.out.println("3:::为空:不执行"));
}
}
打印结果:
1:::false
2:::不为空:执行此Lambda表达式
转换Optional对象值
| 方法名 | 功能 |
|---|---|
| map(Function<? super T, ? extends U> mapper) | 如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional |
| flatMap(Function<? super T, Optional> mapper) | 如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional |
| filter(Predicate<? super T> predicate) | 如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional |
使用示例如下:
public class OptionalTest {
public static void main(String[] args) {
/**
* 用字符串test初始化一个Optional对象,调用map方法替换Optional的值,再调用orElse方法返回Optional对象值
*/
System.out.println("1:::" + Optional.ofNullable("test").map(t -> "changed").orElse("default"));
System.out.println("2:::" + Optional.empty().map(t -> "changed").orElse("default"));
System.out.println("3:::" + Optional.ofNullable("test").flatMap(t -> Optional.of("changed")).orElse("default"));
System.out.println("4:::" + Optional.of("test").filter(t -> true).orElse("default"));
}
}
打印结果:
1:::changed
2:::default
3:::changed
4:::test
map(mapper) 与 flatMap(mapper)区别:
功能上基本是一样的,只是最后的返回值不一样。map(mapper)方法中的mapper可以返回任意类型,但是flatMap(mapper)方法中的mapper只能返回Optional类型
Optional链式调用
/**
* 普通写法
*/
public String getCity(User user) throws Exception{
if(user!=null){
if(user.getAddress()!=null){
Address address = user.getAddress();
if(address.getCity()!=null){
return address.getCity();
}
}
}
throw new Excpetion("取值错误");
}
/**
* Optional写法
*/
public String getCity(User user) throws Exception{
return Optional.ofNullable(user)
.map(u-> u.getAddress())
.map(a->a.getCity())
.orElseThrow(()->new Exception("取值错误"));
}
当在进行链式调用时,层级越高,使用Optional时,代码会越简介;而使用if判断Null,则相反。
总结
1.虽然Optional链式调用时,代码很简洁,但是可读性却随之降低;在if嵌套判断不多时,笔者建议还是使用if判断NUll,或者使用3元表达式。【参考阿里开发规范】
