【Java8】Optional
功能
Java8引入的java.util.Optional<T>
,提供了一些优雅的方法处理null,可以减少程序中的NullPointerException
。
定义
Optional<T>
是一个容器对象,可以保存类型为T的空值或非空值。
声明
public final class Optional<T>
extends Object
构造方法
Optional.of(obj); //传入值为null时,会报NullPointerException
Optional.ofNullable(obj); //传入null,返回Optional.empty();非null,返回Optional.of(obj)
Optional.empty(); //一个空的Optional实例,调用isPresent(),返回false
看起来,第二种方式是最好的。不过,既然其他两种方式都没有被置为私有,应该也有其意义:
- 当我们非常明确传入值不为空时,可以使用第一种方式。例如:刚new出来的对象;非null的常量。
- 不希望
NullPointerException
被隐藏时,也可以使用第一种方式。
最佳实践
我们要怎么去使用Optional实例?假定我们有一个实例Optional<User> user
:
- 存在即返回,无则提供默认值(orElse)
return user.orElse(UNKNOWN_USER); //而不是return user.isPresent()? user.get():null;
- 存在即返回,无则由函数产生(orElseGet)
return user.orElseGet(() -> fetchAUserFromDatabase());
- 存在则对它进行操作(ifPresent)
user.ifPresent(System.out::println);
//而不是下面的代码
if (user.isPresent()) {
System.out.println(user.get());
}
map函数
当user.isPresent()
为真时,返回它的Username属性值;为假,则返回一个空集合。可以使用map函数实现。
return user.map(u -> u.getUsername()).orElse(Collections.emptyList())
//之前的做法
if(user.isPresent()) {
return user.get().getUsername();
} else {
return Collections.emptyList();
}
map是可以无限级联的,比如再深一层,获得用户名的大写形式:
return user.map(u -> u.getUsername())
.map(name -> name.toUpperCase())
.orElse(null);
没有Optional时的做法:
//之前的做法
User user = .....
if(user != null) {
String name = user.getUsername();
if(name != null) {
return name.toUpperCase();
} else {
return null;
}
} else {
return null;
}
过滤值
除了转换值,Optional类也提供了按条件过滤值的方法filter()
。它接受一个Predicate参数,返回测试结果为true的值。如果测试结果为false,则返回一个空的Optional。示例:根据基本的电子邮箱验证来决定接受或拒绝User。
User user = new User("[email protected]","123");
Optional<User> result = Optional.ofNullable(user)
.filter(u -> u.getEmail() != null && u.getEmail().contains("@"));
返回异常
Optional定义了orElseThrow()
,它会在对象为空的时候抛出异常,而不是返回备选的值:
Optional.ofNullable(user).orElseThrow( () -> new IllegalArgumentException() );
这里,如果user值为null,会抛出IllegalArgumentException
。这个方法让我们有更丰富的语义,可以决定抛出什么样的异常,而不总是抛出NullPointerException
。
杂谈
- Optional没有继承Serializable,所以,它不可以直接做为类的属性。如果需要,可以这样写:
private Address address;
public Optional<Address> getAddress(){
return Optional.ofNullable(address);
}
- Optional尽量不要作为方法参数,会让代码变的复杂,没有必要。可以通过重载来处理。
- Optional主要用作返回类型。在获取到这个类型的实例后,如果它有值,你可以取得这个值,否则可以设置替代行为。
- Optional类有一个非常有用的用例,就是将其与流(Java9支持)或者其它返回Optional的方法结合,完成更复杂的操作。
参考资料:https://blog.csdn.net/hj7jay/article/details/52459334
参考资料:https://www.cnblogs.com/zhangboyu/p/7580262.html
参考资料:https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
上一篇: Java8 Optional
下一篇: java8 Optional