“hi 伙计,你的代码又抛出了一个NullPointerException,哈哈!”
“你烦不烦人,事情辣么多,我可没时间去检查null。”
开始使用Optional
如下的null check代码在一般的项目中就特别的多:
// code1
User user = userService.getUserById(12);
if (null != user) {
// balabala
}
Java8 提供了Optional,其实就是一个对象的容器,通过一个容器去操作里面的对象,这确实会带来很多遍历。这篇文章对Optional的用法阐述得很详细:Java 8 Optional类深度解析
使用Optional改变上面那段代码:
// code2
Optional<User> userOptional = Optional.ofNullable(userService.getUserById(12));
if (userOptional.isPresent()) {
// balabala
}
这样写,看不到有null !=
的代码了,但和code1也没有什么区别,还看不到使用Optional的好处。那就来看看Optional正确的使用姿势:Java 8 Optional—Replace Your Get() Calls
替换上面code2的代码为:
// code3
Optional<User> userOptional = Optional.ofNullable(userService.getUserById(12)).ifPresent(this::doSomething);
还有一些常用的:
// 如果不存在想抛出一个异常
Optional<User> userOptional = Optional.ofNullable(userService.getUserById(12)).orElseThrow(IllegalArgumentException::new);
// 返回默认值
// code4
public String getUserName(Long userId) {
return Optional.ofNullable(getUserNameById(userId)).orElse("");
}
/**
这样的代码就可以使用code4替换掉
public String getUserName(String userId) {
String name = "";
Optional<String> nameOptional = Optional.ofNullable(getUserNameById(userId));
if (nameOptional.isPresent()) {
name = nameOptional.get();
}
return name;
}
*/
这样代码行数减少了,可读性也会好点(仁者见仁智者见智吧),链式调用正好一气呵成——cool。
更多优雅的使用姿势:Java8 如何正确使用 Optional
Optional作为返回值
public Optional<User> getUserById(Long userId) {
return Optional.ofNullable(userMapper.selectUserById(userId));
}
当你使用Optional作为返回值的时候,你已经在考虑可能出现null的情况了,并在客户端进行调用的时候你会进行必要的判断,然后才去Optional中get出想要的值,结合IfPresent()、使用lambda表达式还是一个不错的体验呢!
Optional注意事项
正所谓有得必有失,在使用Optional的时候,要注意这些问题:
1. 当使用Optional.of()时,参数如果是null,也会抛出NullPointerException;
2. Optional本身对象也可以是null,如果本身是null,调用isPresent()的时候也会抛出NullPointerException;
3. Optional增加了堆的大小,并使得调试变得麻烦。Optional是一个包装对象,也就是会使用到两个对象引用;
4. 序列化Optional对象会变得困难,所以在给外部client提供接口(比如提供给其他系统调用的soa接口)时,返回值尽量别是Optional的。
这哥们就很不看好Optional,笑哭:
Java 8 Optional: What’s the Point?
我曾踩过的一个坑
除了序列化的问题,涎于Optional的优点,我还是会在代码中结合lambda表达式、大量使用Optional的。