Optional详解
先说说为什么要写这么一篇博客,因为在看公司代码的过程中,遇到了大量的非空判断,看起来一点都不舒服,代码冗余,所以就想到了java8里面的Optional这个类,在此简单对Optional这个类以及简单的用法做个详细介绍(也是严格意义上的第一篇博客,后续还有)
一.Optional简介
1.1 Optional是什么
个人理解,Optional是一个含有可选值的包装类,也可以说是一个容器,这个容器里面,可以保存类型为T的值,也可以保存null
1.2 Optionaln作用
Optional主要解决的就是空指针异常,在以往的程序中,要做一些逻辑处理的时候,需要做非空判断,这就需要很多的if else代码,使代码看起来变得冗余,使用Optional这个类,就可以解决这个问题
在使用Optional优化if else代码之前,先看看optional这个类相关的API,以便我们更方便的了解和使用它
二:Optional的相关API
2.1 Optional的构造函数
1.Optional.of(obj):它要求传入的 obj 不能是 null 值的, 否则直接报NullPointerException 异常。
2.Optional.ofNullable(obj):它以一种智能的,宽容的方式来构造一个 Optional 实例,来者不拒,传 null 进到就得到 Optional.empty(),非 null 就调用 Optional.of(obj).
3.Optional.empty():返回一个空的 Optional 对象
2.2 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的使用
3.1 用来抛出自定义异常
在以往的程序中,如果出现某些字段为空,需要抛出自定义的异常,在没有使用Optional之前,代码如下
if (school==null){
// 这里抛出自定义的异常,以及异常信息
throw new Exception();
}
使用Optional之后,一行代码搞定,当然这个简单的小demo并不能体现Optional的牛逼之处,接下来再看一个demo
Optional.ofNullable(school).orElseThrow(()->new Exception());
3.2 获取某个字段的值
假如有这样三个类
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class School {
private Teacher teacher;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Teacher {
private Student student;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Student{
private String name;
private int age;
}
如果要获取 Student类中的name属性的值,以往的代码这样写
String name01 = null;
if (school!=null){
if (school.getTeacher()!=null){
if (school.getTeacher().getStudent()!=null){
name01 = school.getTeacher().getStudent().getName();
}
}
}
看看上面这些代码,这是人写的?看都不想看呐,使用了Optional以后,代码是这个样子
String name02 = Optional.ofNullable(school)
.map(s->s.getTeacher())
.map(t->t.getStudent())
.map(d->d.getName())
// orElse里面可以写当name这个属性值为null的时候,你可以设置一个返回值
.orElse(null);
3.3 根据条件过滤,获取某个属性的值
以前代码在进行条件判断的时候,依然要使用if else,这玩意写都写烦了,看起来跟个粗糙大汉一样,毫无美观
int age = 0;
if (school!=null){
if (school.getTeacher()!=null){
if (school.getTeacher().getStudent()!=null){
if (school.getTeacher().getStudent().getAge()>20){
age = school.getTeacher().getStudent().getAge();
}else {
age = 20;
}
}
}
}
使用了Optional以后,瞬间就像整容了一样
int age = Optional.ofNullable(school)
.map(s->s.getTeacher())
.map(t->t.getStudent())
.map(s->s.getAge())
.filter(a-> a>20)
.orElse(20);
当然,以上只是举例一些Optional的使用,在开发过程中,肯定还有其他用法,这里就不多哔哔了,各位大佬自己研究