Java8新特性学习(二)- Optional类

背景

Optional是一个容器,用来管理一个对象。主要是用来解决null和NullPointerException问题。

Java7 -> Java8 Optional是如何简化你的代码

假设有一个Student类

@Data
public class Student {
    private String name;
    private Integer age;

    public Student() {
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

举例一

    //java7
    private String getJava7UpperCaseStudentName(Student student) {
        if (student != null) {
            String name = student.getName();
            if (name != null) {
                return name.toUpperCase();
            }
        }
        return null;
    }

    //java8
    private String getJava8UpperCaseStudentName(Student student) {
        return Optional.ofNullable(student).map(Student::getName).map(String::toUpperCase).orElse(null);
    }

举例二

    @Test
    public void testOptionalOrElse() {
        Student origin = null;
        Student defaultStudent = new Student("default", -1);

        //java7
        Student java7Student = origin != null ? origin : defaultStudent;

        //java8
        Student java8Student = Optional.ofNullable(origin).orElse(defaultStudent);
        System.out.println("java7Student : " + java7Student);
        System.out.println("java8Student : " + java8Student);
    }

可见,使用Optional可以简化代码。

用法及测试

of()、ofNullable()和empty()

    @Test
    public void testEmptyOptional() {
        Optional<Student> emptyOptional = Optional.empty();
        System.out.println("emptyOptional.isPresent:" + emptyOptional.isPresent());
    }

    @Test
    public void testOptional() {
        Optional<Student> nullStudentOptional = Optional.ofNullable(null);
        Optional<Student> studentOptional = Optional.of(new Student("a", 1));
        System.out.println("nullStudentOptional:" + nullStudentOptional.orElse(null));
        System.out.println("studentOptional:" + studentOptional.orElse(null));
    }

输出结果

emptyOptional.isPresent:false
nullStudentOptional:null
studentOptional:Student(name=a, age=1)

of()函数传入的Object不能为空,否则会直接抛出空指针异常

ofNullable()函数传入的Object可为空

empty()函数会创建一个空的Optional对象,其value为null

isPresent()

    @Test
    public void testOptionalIsPresent() {
        Optional<Student> nullStudentOptional = Optional.ofNullable(null);
        Optional<Student> studentOptional = Optional.of(new Student("a", 1));
        System.out.println("nullStudentOptional.isPresent():" + nullStudentOptional.isPresent());
        System.out.println("studentOptional.isPresent():" + studentOptional.isPresent());
    }

输出结果

nullStudentOptional.isPresent():false
studentOptional.isPresent():true

isPresent()函数会判断当前Optional容器保存的对象是否不为空,true表示不为空,false表示为空

IfPresent()

    @Test
    public void testOptionalIfPresent() {
        Optional<Student> studentOptional1 = Optional.of(new Student("a", 1));
        studentOptional1.ifPresent(student -> {
            System.out.println("accept student:" + student);
            student.setAge(student.getAge() * 2);
            student.setName(student.getName() + "-accept");
        });
        System.out.println("after accept student:" + studentOptional1.orElse(null));
    }

运行结果

accept student:Student(name=a, age=1)
after accept student:Student(name=a-accept, age=2)

orElseThrow()、orElseGet()

    @Test
    public void testOptionalOrElseThrow() {
        Optional<Student> studentOptional = Optional.ofNullable(null);
        Student student = studentOptional.orElseThrow(() -> new NullPointerException("studentOptional is null"));
        System.out.println("student : " + student);
    }

    @Test
    public void testOptionalOrElseGet() {
        Optional<Student> studentOptional = Optional.ofNullable(null);
        Student student = studentOptional.orElseGet(() -> new Student("zz", -1));
        System.out.println("student : " + student);
    }

输出结果

结果1:
java.lang.NullPointerException: studentOptional is null

	at com.common.java8.OptionalTest.lambda$testOptionalOrElseThrow$7(OptionalTest.java:56)
	at java.util.Optional.orElseThrow(Optional.java:290)
	at com.common.java8.OptionalTest.testOptionalOrElseThrow(OptionalTest.java:56)...

结果2:
student : Student(name=zz, age=-1)

map()、flatMap()

    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }

    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
    }

从方法签名上看,两者返回参数相同,入参Function的返回参数不一样,一个是U,一个是Optional< U >, 但是他们都返回Optional< U >

    @Test
    public void testOptionalMapAndFlatMap() {
        Optional<Student> studentOptional = Optional.of(new Student("aa", 11));
        System.out.println("map:" + studentOptional.map(Student::getName).orElse(null));
        System.out.println("flatMap:" + studentOptional.flatMap(s -> Optional.of(s.getName())).orElse(null));

        Optional<Student> nameNullOptional = Optional.of(new Student(null, 11));
        System.out.println("map:" + nameNullOptional.map(Student::getName).orElse(null));
        System.out.println("flatMap:" + nameNullOptional.flatMap(s -> Optional.ofNullable(s.getName())).orElse(null));
        System.out.println("flatMap:" + nameNullOptional.flatMap(s -> null).orElse(null));
    }

输出结果

map:aa
flatMap:aa
map:null
flatMap:null

java.lang.NullPointerException
	at java.util.Objects.requireNonNull(Objects.java:203)
	at java.util.Optional.flatMap(Optional.java:241)
	at com.common.java8.OptionalTest.testOptionalMapAndFlatMap(OptionalTest.java:23)

从上面这种用法两者基本相同。但是在Optional类中,两个方法真正的区别是flatMap返回的必须是一个非空Optional值,否则会抛出NullPointException.

  • 0
    点赞
  • 1
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论

打赏作者

codingtu

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值