Java8特性之Optional

2020-05-21  本文已影响0人  文景大大

一、什么是Optional

Optional从名字上看,意思应该是可选项的意思,那么在Java8的实际使用中,我们就是使用它来表示一个可以为空的对象,给开发者提供了一种可以不用判断非空的程序写法,更加地易读和优雅。

比如,我们创建两个方法,分别用来获取空对象和非空对象:

private Person getNullPerson(){
        return null;
}
private Person getPerson(){
        return new Person("mason",22, 3500.0);
}

如果我们不使用Optional,那么我们可能会写出这样的代码:

    @Test
    public void test01(){
        Person person = getNullPerson();
        // 直到使用的时候才报出NPE
        log.info("员工的姓名为:{},年龄为:{},薪水为:{}", person.getName(), person.getAge(), person.getSalary());
    }

这段代码很容易就出现NPE,所以我们一般这样写:

    @Test
    public void test01(){
        Person person = getNullPerson();
        if(person != null){
            // 每次使用都需要进行非空判断,非常繁琐,容易遗忘
            log.info("员工的姓名为:{},年龄为:{},薪水为:{}", person.getName(), person.getAge(), person.getSalary());
        }
    }

可以看到,这样写比较繁琐,我们完全可以使用Optional来完成这个例子:

    @Test
    public void test03(){
        // 提前报出NPE问题,而不是等到使用的时候才发现
        Optional<Person> optional = Optional.of(getNullPerson());
        Person person = optional.get();
        log.info("员工的姓名为:{},年龄为:{},薪水为:{}", person.getName(), person.getAge(), person.getSalary());
    }

在如上的例子中,只要Optional.of的对象是空的,那么就会提前抛出NPE问题,而不是等到使用的时候才发现。

这么一看,代码好像也没有变得更加精简,Optional也没有体现它的优雅和简洁。别着急,我们先来看看Optional的一些常规用法。

二、Optional的使用

三、为什么要使用Optional

我们在日常的使用中,经常会遇到这样的场景:

@Data
public class Home {
    private String address;

    public Home(){}

    public Home(String address){
        this.address = address;
    }
}

@Data
public class Person {
    private String name;
    private Integer age;
    private Double salary;
    private Home home;

    public Person(){}

    public Person(String name, Integer age, Double salary){
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
}
    @Test
    public void test15(){
        Person person = getNullPerson();
        if(person != null){
            Home home = person.getHome();
            if(home != null){
                String address = home.getAddress();
                log.info("员工的地址为:{}", address);
            }
        }
    }

我们尝试打印Person中的Home中的address属性,不得不做两次非空校验,而且,对于Person和Home任一为空的情况没有做任何的处理,否则,将还会多出来两个else语句,十分繁琐,冗余。

但是如果我们使用Optional会怎样?

@Data
public class Person {

    private String name;
    private Integer age;
    private Double salary;
    private Optional<Home> home = Optional.empty();

    public Person(){}

    public Person(String name, Integer age, Double salary){
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
}
    @Test
    public void test14(){
        // 创建一个可以为空的实例
        String address = Optional.ofNullable(getNullPerson()).orElse(getDefaultPerson())
                .getHome().orElseGet(() -> new Home("China!!!")).getAddress();
        log.info("员工的地址为:{}", address);
    }

在上面的例子中,我们完全实现了test15的功能,除此之外,还对Person为空和Home为空的情况做了默认值设置,大大提升了易读性,变得更加优雅。

上一篇下一篇

猜你喜欢

热点阅读