Java8新特性Optional - 消灭空指针异常
欢迎来我的博客参观,交流:https://endwas.cn
前言:
空指针异常在Java中的出现就好像死亡在你生命中一样,你无法避免也无法拒绝。不可否认null对象在编程上给我们带来很多便利,但在便捷的同时,要求开发人员仔细检查、校验。相信我们在写代码中的时候都写过无数个if xx = null …这种代码,这篇博客就是教你使用Optional代替没有营养的校验,然后开启你的函数式编程。
- 空指针引用:价值十亿美元的错误
我称之为我的十亿美元错误……当时,我正在设计第一个全面的类型系统,用于面向对象语言中的引用功能。我的目标是确保所有对引用的使用都是绝对安全的,由编译器自动执行检查。但是我无法拒绝定义一个 Null 引用的诱惑,因为它实在太容易实现了。这导致了无数错误、漏洞和系统崩溃。在过去的四十年里,这些问题可能已经造成了十亿美元的损失。 ——托尼·霍尔,ALGOL W 的发明者。
1.Optional介绍
Optional 是 Java 实现函数式编程的强劲一步,并且帮助在范式中实现。但是 Optional 的意义显然不止于此。
我们从一个简单的用例开始。在 Java 8 之前,任何访问对象方法或属性的调用都可能导致 NullPointerException:
String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();
在上面的任何一个调用都有可能抛出空指针异常,那么我们就需要做判断
// 查询国家码
public String getIsoCode(User user) {
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
String isocode = country.getIsocode();
if (isocode != null) {
isocode = isocode.toUpperCase();
return isocode;
}
}
}
}
return "null";
}
为了不再嵌套if语句判断,外加没意义没营养的取值,我们使用Optional来看看效果
public String getIsoCode(User user) {
return Optional.ofNullable(user)
.map(a -> a.getAddress())
.map(a -> a.getCountry())
.map(a -> a.getIsocode())
.map(a -> a.toUpperCase())
.orElse("CHINA");
}
2.Optional使用
2.1 创建Optional对象
这个类的构造方法是私有的,同时他也无法被继承,所以要创建该对象只能使用它内置的两个静态方法 of、ofNullable或者empty方法创建value为null的Optional对象。
// 如果为空抛出空指针异常
Optional.of(null);
// 如果为空插入value设置为空
Optional.ofNullable(null);
// 创建空的对象
Optional.empty()
2.2 isPresent 、ifPresent
从字面意思两者极其相似,都是判断是否存在,但通过源码,还是能看到区别;
isPresent:判断该对象的value是否存在,没有入参,返回值boolean
ifPresent:判断该对象的value是否存在,如果存在执行传入的函数,入参为对应的函数实现,无返回值
User user = new User("endwas", 45);
// 返回值判断value是否不为空
boolean present = Optional.ofNullable(user.getName()).isPresent();
// 当value不为空时候才对该value执行函数式编程
Optional.ofNullable(user.getName()).ifPresent(System.out::println);
2.3 orElse、orElseGet、orElseThrow
这两个方法从意思上也挺类似,都是在value为空时,我们要怎么处理;
orElse是当value的值为null时,返回传入的值;
orElseGet则是当value的值为null时,返回函数式方法执行结果。
orElseThrow是当value值为null时,抛出传入的异常
User user = new User(null, 45);
// value不为null时返回value,否则返回orElse内的值,【注:两者必须同一类型
String orElse = Optional.ofNullable(user.getName()).orElse("orElse");
// value不为null时返回value,否则调用orElse方法,orElse无入参有返回值为传入的类型
String orElseGet = Optional.ofNullable(user.getName()).orElseGet(() -> {
String returnValue = "retrun orElseGet";
return returnValue;
});
String orElseThrow = Optional.ofNullable(user.getName()).orElseThrow(()->new RuntimeException("errororor"));
System.out.println(orElseThrow);
2.4 filter
filter就是过滤器,他传入的也是一个函数式方法,他的作用就是对value进行过滤,如果满足过滤条件true则返回原Optional对象,反之返回empty对象;类似stream中的filter对象
User user = new User("endwas", 45);
// 对user.name进行过滤如果以“end”开头则返回原对象,否则返回空,然后打印
Optional.of(user.getName()).filter(value -> value.startsWith("end")).ifPresent(System.out::println);
2.5 map、flatMap
map()和flatMap()对Optional中的对象进行转换值的操作,这两个方法唯一的区别就是接受的参数不同。
注意:value不能为null,否则直接返回empty不会执行map方法
map()方法的mapping函数返回值可以是任何类型T,然后在map中封装好返回,而flatMap()方法的mapping函数则是你需要在函数方法中封装好Optional,然后返回该对象。
User user = new User("endwas", 45);
// map返回值为任意类型,然后把它封装成Optional对象
Optional.of(user).map(u -> u.getName()).ifPresent(System.out::println);
// flatMap返回值为
Optional.of(user).flatMap(u -> Optional.ofNullable(u.getName())).ifPresent(System.out::println);
总结:
- Optional本质是为了解决日常开发中对象判断为null情形,使用链式开发,更加优雅。
- Optional内部封装了value属性,同时对value使用,进行了严格判定,避免空指针异常情形
上一篇: JAVA - 【Optional】辅助防止空指针异常
下一篇: flexigrid自定义绑定数据源
推荐阅读