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.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章