Java语言11之Optional

1 Optional类

1.1 为什么引入Optional类

Java 8中引入了一个新的类java.util.Optional,其目的就是用于解决可能存在的空指针异常问题。举例来说,如果你知道一个人可能有也可能没有车,那么Person类内部的car变量就不应该声明为Car,遭遇某人没有车时把null引用赋值给它,而是应该直接将其声明为Optional类型。
在这里插入图片描述

  • Optional类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
  • Optional是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
  • Optional类的引入很好的解决空指针异常。

1.2 相关API

创建对象相关:

  • Optional.empty():创建一个空的Optional实例。
  • Optional.of(T t):创建一个Optional实例,当t为null时抛出异常(NullPointerException)。
  • Optional.ofNullable(T t):创建一个Optional实例,但当t为null时不会抛出异常,而是返回一个空的实例。

获取对象相关:

  • get():获取optional实例中的对象,当optional容器为空时报错。

  • orElse(T other):如果optional不为空,则返回optional中的对象;如果为null,则返回other 这个默认值。

  • orElseGet(Supplier other):如果optional不为空,则返回optional中的对象;如果为null,则使用Supplier函数生成默认值other。

  • orElseThrow(Supplier exception):如果optional不为空,则返回optional中的对象;如果为null,则抛出Supplier函数生成的异常。

对象映射相关:

  • map(Function<T, U> mapper):如果optional不为空,则将optional中的对象t映射成另外一个对象u,并将u存放到一个新的optional容器中。
  • flatMap(Function<T,Optional > mapper):跟上面一样,在optional不为空的情况下,将对象t映射成另外一个optional。
  • filter(Predicate p):filter()接受一个Predicate参数,返回测试结果为true的值。如果测试结果为false,会返回一个空的Optional。

判空相关:

  • isPresent():判断optional是否为空,如果空则返回false,否则返回true。
  • ifPresent(Consumer c):如果optional不为空,则将optional中的对象传给Comsumer函数。

2 API Demo

2.1 创建一个对象

@Data

@Accessors(chain = true)

public class Person {

  private String name;

  private Integer age;

  private Optional<Car> cars;

 

  @Data

  @Accessors(chain = true)

  public static class Car {private String name;

  }

}

2.2 测试创建对象相关API

@Slf4j

public class PersonTest1 {

 

  @Test

  public void testOf() {Optional<Person> person1 = Optional.of(getPerson());System.out.println("person1 = " + person1);try {Optional<Person> person2 = Optional.of(null);System.out.println("person2 = " + person2);} catch (NullPointerException e) {

​      log.error("of() 不支持传入null");}

  }

 

  @Test

  public void testOfNullable() {Optional<Person> person1 = Optional.ofNullable(getPerson());System.out.println("person1 = " + person1);Optional<Person> person2 = Optional.ofNullable(null);System.out.println("person2 = " + person2);

  }

 

  @Test

  public void testEmpty() {Optional<Person> person = Optional.empty();try {System.out.println("person = " + person.get());} catch (NoSuchElementException e) {

​      log.error("NoSuchElementException");}

  }

 

  private Person getPerson() {return new Person().setName("Tom").setAge(18);

  }

}

2.3 测试获取对象相关API

@Slf4j
public class PersonTest2 {

    @Test
    public void testOrElse() {
        Person nullPer = null;
        // 如果参数为null的话,就会执行并返回后面的函数
        // 相当于提供一个默认值
        Person person1 = Optional.ofNullable(nullPer).orElse(getSpecialPerson());
        System.out.println("person1 = " + person1);

        Person person2 = Optional.ofNullable(getPerson()).orElse(getSpecialPerson());
        System.out.println("person2 = " + person2);
    }

    @Test
    public void testOrElseGet() {
        Person nullPer = null;
        // 如果参数为null的话,就会执行并返回后面的函数
        Person person1 = Optional.ofNullable(nullPer).orElseGet(this::getSpecialPerson);
        System.out.println("person1 = " + person1);

        Person person2 = Optional.ofNullable(getPerson()).orElseGet(this::getSpecialPerson);
        System.out.println("person2 = " + person2);
    }

    @Test
    public void testOrElseThrow() throws Exception {
        Person nullPer = null;
        try {
            Person student = Optional.ofNullable(nullPer).orElseThrow(() -> new Exception("per is null"));
            System.out.println(student);
        } catch (Exception e) {
            log.error("{}", e.getMessage());
        }
    }

    private Person getPerson() {
        return new Person().setName("Tom").setAge(18);
    }

    public Person getSpecialPerson() {
        System.out.println("测试specialStudent是否被执行了");
        return new Person().setName("Mary").setAge(22);
    }
}

2.4 测试对象映射相关API

@Slf4j
public class PersonTest3 {

    @Test
    public void testMap() {
        Person person = getPerson();
        String name = Optional.of(person).map(Person::getName).get();
        System.out.println("name = " + name);
    }

    @Test
    public void testFlatMap() {
        Person person = getPerson();
        Optional<Person.Car> car = Optional.of(person).flatMap(Person::getCar);
        System.out.println("car = " + car.get());
    }

    private Person getPerson() {
        return new Person().setName("Tom").setAge(18).setCar(Optional.of(new Person.Car()));
    }
}

2.5 测试判空相关API

@Slf4j
public class PersonTest4 {

    @Test
    public void version1() {
        // 极其不优雅,多层嵌套if
        Person student = getPerson();
        if (student != null) {
            doSomething1();
            if (student.getName() != null) {
                doSomething2(student.getName());
            }
        }
    }

    @Test
    public void version2() {
        // 和version1其实没有多大区别,推荐version3
        Optional<Person> student = Optional.ofNullable(getPerson());
        if (student.isPresent()) {
            doSomething1();
            if (student.get().getName() != null) {
                doSomething2(student.get().getName());
            }
        }
    }

    @Test
    public void version3() {
        Optional<Person> student = Optional.ofNullable(getPerson());
        student.ifPresent(stu -> {
            doSomething1();
            stu.getCar().ifPresent(car -> doSomething2(car.getName()));
        });
    }

    private void doSomething1() {
        log.info("do something");
    }

    private void doSomething2(String name) {
        log.info("name: {}", name);
    }

    private Person getPerson() {
        boolean b = new Random().nextBoolean();
        if (b) {
            Person.Car car = new Person.Car().setName("宝马");
            return new Person().setName("Tom").setAge(18).setCar(Optional.of(car));
        } else {
            return null;
        }
    }
}

2.6 测试过滤API

@Slf4j
public class PersonTest5 {

    @Test
    public void testFilter() {
        Optional<Person> opt = Optional.ofNullable(getPerson()).filter(stu -> stu.getName().startsWith("T"));
        opt.ifPresent(stu -> {
            log.info(stu.getName());
        });
    }

    private Person getPerson() {
        boolean b = new Random().nextBoolean();
        if (b) {
            Person.Car car = new Person.Car().setName("宝马");
            return new Person().setName("Tom").setAge(18).setCar(Optional.of(car));
        } else {
            return null;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值