美文网首页
Java8特性之Optional

Java8特性之Optional

作者: 文景大大 | 来源:发表于2020-05-21 21:19 被阅读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的使用

  • of的用法;

    在上面的案例中,我们就已经使用了该方法,获取一个Optional<T>的对象,倘若对象为空,则of方法直接就抛出NPE;对象不为空的话,我们可以通过get来获取该非空T对象;

        @Test
        public void test02(){
            // 正常的使用
            Optional<Person> optional = Optional.of(getPerson());
            Person person = optional.get();
            log.info("员工的姓名为:{},年龄为:{},薪水为:{}", person.getName(), person.getAge(), person.getSalary());
        }
    
  • empty的用法;

    我们可以通过调用empty来获取一个空的Optional<T>对象,如果直接使用该空对象尝试获取T对象的话,就会抛出java.util.NoSuchElementException: No value present,通常情况下,empty只会在声明JavaBean中的属性为空的Optional<T>时使用。

        @Test
        public void test04(){
            // 创建一个空的实例
            Optional<Person> optional = Optional.empty();
            // 如下语句抛出java.util.NoSuchElementException: No value present
            Person person = optional.get();
            log.info("员工的姓名为:{},年龄为:{},薪水为:{}", person.getName(), person.getAge(), person.getSalary());
        }
    
  • ofNullable的用法;

    在上面of的用法中,不允许对象为空,而有的时候,我们仍然需要这个为空的Optional<T>对象,那么就可以使用ofNullable。

        @Test
        public void test05(){
            // 创建一个可以为空的实例
            Optional<Person> optional = Optional.ofNullable(getNullPerson());
            // 如下语句抛出java.util.NoSuchElementException: No value present
            Person person = optional.get();
            log.info("员工的姓名为:{},年龄为:{},薪水为:{}", person.getName(), person.getAge(), person.getSalary());
        }
    
  • isPresent的用法;

    通常ofNullable和isPresent都是配合使用的。

        @Test
        public void test07(){
            Optional<Person> optional = Optional.ofNullable(getNullPerson());
            if(optional.isPresent()){
                Person person = optional.get();
                log.info("员工的姓名为:{},年龄为:{},薪水为:{}", person.getName(), person.getAge(), person.getSalary());
            }
        }
    
  • orElse的用法;

    如果我们使用isPresent,仿佛又回到了!=null的老路子上去了,所以,我们还可以在Optional<T>为空的时候,指定一个默认的非空对象。

        @Test
        public void test10(){
            // 创建一个可以为空的实例
            Person person = Optional.ofNullable(getNullPerson()).orElse(getDefaultPerson());
            log.info("员工的姓名为:{},年龄为:{},薪水为:{}", person.getName(), person.getAge(), person.getSalary());
        }
    
    private Person getDefaultPerson(){
            return new Person("default",20, 3000.0);
        }
    
  • orElseGet的用法;

    和orElse的作用类似,区别是可以指定额外的处理逻辑。

        @Test
        public void test11(){
            // 创建一个可以为空的实例
            Person person = Optional.ofNullable(getNullPerson()).orElseGet(() -> new Person("Jack", 33, 5501.1));
            log.info("员工的姓名为:{},年龄为:{},薪水为:{}", person.getName(), person.getAge(), person.getSalary());
        }
    
  • map的用法;

    我们还可以对T对象进行一些流式处理。

        @Test
        public void test12(){
            // 创建一个可以为空的实例
            Integer age = Optional.ofNullable(getNullPerson())
                    .map((x) -> x.getAge())
                    .map((y) -> y*2)
                    .orElse(45);
            log.info("员工的年龄为:{}", age);
        }
    

三、为什么要使用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为空的情况做了默认值设置,大大提升了易读性,变得更加优雅。

相关文章

  • JAVA8新特性-Optional类解决NPE问题

    ** JAVA8新特性-Optional类解决NPE问题** API介绍 1、Optional(T value),...

  • Optional源码分析(未完)

    Optional源码分析(未完) Optional 类是Java8的新特性,Optional是一个可以为null的...

  • java8 - optional

    optional 是java8的新特性,The purpose of the class is to provid...

  • Java-8-Optional类

    Java-8-Optional类 java8新特性之Optional类 空指针异常是一个运行时异常,对于这一类异常...

  • JAVA8- Optional-用法浅析

    JAVA8- Optional-用法浅析 简介 java8新引入optional特性,官方说法是更优雅的处理空指针...

  • Java8特性之Optional

    一、什么是Optional Optional从名字上看,意思应该是可选项的意思,那么在Java8的实际使用中,我们...

  • Java8中的lambda表达式

    lambda表达式是Java8中最重要的特性之一,也是Stream,Optional等特性的基础。尽管lambda...

  • java8新特性之Optional

    Optional的出现是为了解决java由来已久的null安全问题,正确的使用Optional会让你的代码写得十分...

  • Java8 新特性之 Optional 类

    摘要: Optional不是对null关键字的一种替代,而是对于null判定提供了一种更加优雅的实现 Java8新...

  • java8新特性之Optional类

    Optional类的作用java.util.Optional类是一个包含null值的容器对象,可以代替xx!=nu...

网友评论

      本文标题:Java8特性之Optional

      本文链接:https://www.haomeiwen.com/subject/dgcxahtx.html