JAVASE Optional 类优雅解决空指针异常等操作详解

目录

    • 1. 引入pom依赖
    • 2 JavaBean对象
    • 2.Optional对象测试
      • 2.1 生成Optional对象的三种方式
      • 2.2 `filter:` 过滤当前 Optiona
      • 2.3 `get:` 获取 Optional 包装的对象
      • 2.4 `map:`将方法映射到当前 Optional 中, 并生成一个新的 Optional
      • 2.5 `flatMap:`平滑的将方法映射到当前 Optional 中, 并生成一个新的 Optional
      • 2.6 `ifPresent:`如果值存在就执行指定的方法, 否则什么也不做
      • 2.7 `orElse:` 获取 Optional 的值, 如果 Optional 没有值则返回给定值
      • 2.8`orElseGet:`如果值存在就获取 Optional 的值, 如果值不存在则通过生成函数获取返回值
      • 2.9`orElseThrow:`获取 Optional 的值, 如果值不存在则按着自己给的错误 报错;
      • 2.10 `toString:`返回当前实例的 String 形式
      • 2.11`isPresent:`判断 Optional 的值是否存在
      • 2.12 `ifPresentOrElse:`如果值存在就执行指定的方法, 否则执行空值方法 ==【jdk版本9或以上】==
      • 2.13 `or:`获取带值的 Optional, 如果 Optional 没有值则获得给定函数生成 Optional ==【jdk版本9或以上】==
      • 2.14 `stream:` 获取一个 Optional 的流 ==【jdk版本9或以上】==
  • 链接:[Optional 类优雅解决空指针异常等操作详解 源代码下载地址](https://download.csdn.net/download/JAVA_MHH/22348122)


链接: Optional 官方参考手册

1. 引入pom依赖

Optional对象是 java8里的 所以这里也就引入了几个测试的依赖而已


    <!--依赖父类springboot 2.3.2版本-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>

    <!--Optional对象有几个方法是jdk版本9-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>9</source>
                    <target>9</target>
                </configuration>
            </plugin>
        </plugins>
    </build>



    <dependencies>
        <!--测试包-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <!--简写javabean-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>


2 JavaBean对象

  • 一个普通的测试对象
  • @Data: 自动为所有字段添加@ToString, @EqualsAndHashCode, @Getter方法,为非final字段添加@Setter,和@RequiredArgsConstructor
  • @AllArgsConstructor: 自动生成全参数构造函数。
  • @NoArgsConstructor: 自动生成无参数构造函数。
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

 	@Data
    @AllArgsConstructor
    @NoArgsConstructor
    class Student {
        private String name;
        private Integer age;
    }


2.Optional对象测试

2.1 生成Optional对象的三种方式

  • 生成Optional对象的三种方式
  1. empty 方法: `返回一个空的Optional实例
  2. of 方法: 将指定值用Optional封装之后返回,如果该值为null,则抛出一个NullPointerException异常
  3. ofNullable方法: 将指定值用Optional封装之后返回,如果该值为null,则返回一个空的Optional对象

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {


    /*
     * 生成Optional对象的三种方式
     *     1.empty 方法 :返回一个空的Optional实例
     *    2.of 方法 :将指定值用Optional封装之后返回,如果该值为null,则抛出一个NullPointerException异常
     *   3.ofNullable方法:将指定值用Optional封装之后返回,如果该值为null,则返回一个空的Optional对象
     * */
    @Test
    public void optionalGenerate() {

        //--------------1.empty方法:返回一个空的Optional实例----------------
        Optional<Object> empty = Optional.empty();
        System.out.println(empty); //Optional.empty

        //------2.of方法:将指定值用Optional封装之后返回,如果该值为null,则抛出一个NullPointerException异常
        Student student = new Student();
        //   -- 如果 of里存的对象是个null则报错-->java.lang.NullPointerException
        Optional<Student> optionalStudent = Optional.of(student);
        System.out.println(optionalStudent); //Optional[Student(name=null, age=null)]

        //---3.ofNullable方法:将指定值用Optional封装之后返回,如果该值为null,则返回一个空的Optional对象---
        Student ofNullableStudent = new Student();
        //--如果是存入的对象是null 那么返回的就是空的Optional实例,如果有则返回Optional封装之后的对象
        Optional<Student> ofNullableStudentOptional = ofNullable(ofNullableStudent);
        System.out.println(ofNullableStudentOptional);
    }
}



2.2 filter: 过滤当前 Optiona

  • filter 方法 : 如果值存在并且满足提供的谓词,就返回包含该值的Optional对象;否则返回一个空的 Optional对象

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {


       /*
     * filter 方法 :如果值存在并且满足提供的谓词,就返回包含该值的Optional对象;
     *                                          否则返回一个空的 Optional对象
     *
     * */
    @Test
    public void filterOptional() {
        Student student = new Student(null, 12);
        Optional<Student> studentOptional = Optional.of(student);

        Optional<Student> filterOptional = studentOptional.filter(s -> {
            return s.getAge() > 18;
        });
        System.out.println(studentOptional);//Optional[TestDemo.Student(name=null, age=12)]
        System.out.println(filterOptional);//Optional.empty
        System.out.println(studentOptional == filterOptional); //false
    }
}



2.3 get: 获取 Optional 包装的对象

  • get 方法 : 如果该值存在,就返回Optional封装的对象,否则抛出一个NoSuchElementException异常

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {

    /*
     *
     * get 方法 :如果该值存在,就返回Optional封装的对象,否则抛出一个NoSuchElementException异常
     * */
    @Test
    public void getOptional() {
        Student student = new Student(null, 12);
        Optional<Student> studentOptional = ofNullable(student);

        //这里如果是个空的Optional对象,则就会报java.util.NoSuchElementException: No value present
        Student getStudent = studentOptional.get();
        System.out.println(getStudent);//Student(name=null, age=12)
    }
}



2.4 map:将方法映射到当前 Optional 中, 并生成一个新的 Optional

  • 简单来说[flatMap]与[map] 之间区别:
             map源码里自动帮你把参数封装到Optional里了,flatMap需要你自己封装下返回
  • map:
          如果Optional是空的 则就不会执行提供的mapping函数调用
          如果Optional不是空的 则就会执行提供的mapping函数调用

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {
	/*
     * 简单来说[flatMap]与[map] 之间区别:  就是map源码里自动帮你把参数封装到Optional里了,flatMap需要你自己封装下返回
     * 如果Optional是空的 则就不会执行提供的mapping函数调用
     * 将方法映射到当前 Optional 中, 并生成一个新的  Optional
     * */
    @Test
    public void mapOptional() {
        Student student = new Student("小白", 12);
        Optional<Student> studentOptional = ofNullable(student);//todo(传个null测试 用来验证会不会执行提供的mapping函数调用)
//        Optional optionalName = studentOptional.map(Student::getName);
        Optional<String> optionalName = studentOptional.map(s -> {
//            return true;
            System.out.println("执行mapOptional--name");
            return s.name;
        });
        System.out.println(optionalName); //Optional[小白]

//        Optional optionalInteger = studentOptional.map(Student::getAge);
        Optional<Integer> optionalInteger = studentOptional.map(s -> {
//            return true;
            System.out.println("执行mapOptional--age");
            return s.age;
        });
        System.out.println(optionalInteger);//Optional[12]
    }
}



2.5 flatMap:平滑的将方法映射到当前 Optional 中, 并生成一个新的 Optional

  • 简单来说[flatMap]与[map] 之间区别:
             map源码里自动帮你把参数封装到Optional里了,flatMap需要你自己封装下返回
  • flatMap:
          如果Optional是空的 则就不会执行提供的mapping函数调用
          如果Optional不是空的 则就会执行提供的mapping函数调用

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {
/*
     *  简单来说[flatMap]与[map] 之间区别:  就是map源码里自动帮你把参数封装到Optional里了,flatMap需要你自己封装下返回
     * 如果Optional是空的 则就不会执行提供的mapping函数调用
     * 将方法映射到当前 Optional 中, 并生成一个新的  Optional
     * */
    @Test
    public void flatMapOptional() {
        Student student = new Student("小白", 12);
        Optional<Student> studentOptional = ofNullable(student);//todo(传个null测试 用来验证会不会执行提供的mapping函数调用)
//        Optional optionalName = studentOptional.map(Student::getName);
        Optional<String> optionalName = studentOptional.flatMap(s -> {
//            return true;
            System.out.println("执行flatMapOptional--name");
            return ofNullable(s.name);
        });
        System.out.println(optionalName); //Optional[小白]

//        Optional optionalInteger = studentOptional.map(Student::getAge);
        Optional<Integer> optionalInteger = studentOptional.flatMap(s -> {
//            return true;
            System.out.println("执行flatMapOptional--age");
            return ofNullable(s.age);
        });
        System.out.println(optionalInteger);//Optional[12]

    }
}



2.6 ifPresent:如果值存在就执行指定的方法, 否则什么也不做

  • 如果Optional是空的 则就不会执行ifPresent()方法里的程序代码

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {

 /*
     * 和map或flatMap一块使用 带劲  map会返回Optional,链式编程
     * 如果Optional是空的 则就不会执行ifPresent()方法里的程序代码
     * */
    @Test
    public void ifPresentOptional() {
        Student student = new Student("小白", 12);
        Optional<Student> studentOptional = ofNullable(student);
        studentOptional.ifPresent(s -> {
            System.out.println("执行了ifPresent里的程序");
        });
    }
}



2.7 orElse: 获取 Optional 的值, 如果 Optional 没有值则返回给定值

  • 如果Optional 为空 那么就返回 给orElse的入参值;
  • orElse与orElseGet与orElseThrow区别 :
        1. orElse() 直接把默认值直接当作入参传进去,当此Optional为空的时候 返回默认值
        2. orElseGet()通过函数程序方法 最后return返回最终结果默认值,当此Optional为空的时候 返回默认值
        3. orElseThrow()默认值是给的一个错误… 如果 此Optional为空的 就报给的错误;

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {

 /*
     * 获取 Optional 的值, 如果 Optional 没有值则返回给定值.
     * orElse与orElseGet与orElseThrow区别 :
     *              orElse() 直接把默认值直接当作入参传进去,当此Optional为空的时候 返回默认值
     *              orElseGet()通过函数程序方法 最后return返回最终结果默认值,当此Optional为空的时候 返回默认值
     *              orElseThrow()默认值是给的一个错误.... 如果 此Optional为空的 就报给的错误;
     * */
    @Test
    public void orElseOptional() {
        Optional<String> nameOptional = Optional.of("小白");
        String name = nameOptional.orElse("小黑");
        System.out.println(name);//小白
        String orElseName = (String) nameOptional.map(s -> { //这里把nameOptional置为空的Optional实例
            return null;
        }).orElse("小黑");
        System.out.println(orElseName);//小黑
    }

}



2.8orElseGet:如果值存在就获取 Optional 的值, 如果值不存在则通过生成函数获取返回值

  • 如果值存在则返回 Optional 的值, 否则返回生成函数的执行结果.
  • orElse与orElseGet与orElseThrow区别 :
        1. orElse() 直接把默认值直接当作入参传进去,当此Optional为空的时候 返回默认值
        2. orElseGet()通过函数程序方法 最后return返回最终结果默认值,当此Optional为空的时候 返回默认值
        3. orElseThrow()默认值是给的一个错误… 如果 此Optional为空的 就报给的错误;
  • 抛出的异常: NoSuchElementException 如果值不存在

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {
 /*
     * 获取 Optional 的值, 如果值不存在则通过生成函数获取返回值;
     *    orElse与orElseGet与orElseThrow区别 :
     *              orElse() 直接把默认值直接当作入参传进去,当此Optional为空的时候 返回默认值
     *              orElseGet()通过函数程序方法 最后return返回最终结果默认值,当此Optional为空的时候 返回默认值
     *              orElseThrow()默认值是给的一个错误.... 如果 此Optional为空的 就报给的错误;
     * */
    @Test
    public void orElseGetOptional() {

        Optional<String> nameOptional = Optional.of("小白");
        String name = nameOptional.orElse("小黑");
        System.out.println(name);//小白
        String orElseName = (String) nameOptional.map(s -> { //这里把nameOptional置为空的Optional实例
            return null;
        }).orElseGet(() -> {
            System.out.println("执行orElseGet中的函数,然后获取到最终结果当作默认值返回");
            return "小黑";
        });
        System.out.println(orElseName);//小黑
    }
}



2.9orElseThrow:获取 Optional 的值, 如果值不存在则按着自己给的错误 报错;

  • 获取Optional的值 如果值不存在则按着自己给的错误 报错;
  • orElse与orElseGet与orElseThrow区别 :
        1. orElse() 直接把默认值直接当作入参传进去,当此Optional为空的时候 返回默认值
        2. orElseGet()通过函数程序方法 最后return返回最终结果默认值,当此Optional为空的时候 返回默认值
        3. orElseThrow()默认值是给的一个错误… 如果 此Optional为空的 就报给的错误;

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {

/*
     * 获取 Optional 的值, 如果值不存在则按着自己给的错误 报错;
     * orElse与orElseGet与orElseThrow区别 :
     *              orElse() 直接把默认值直接当作入参传进去,当此Optional为空的时候 返回默认值
     *              orElseGet()通过函数程序方法 最后return返回最终结果默认值,当此Optional为空的时候 返回默认值
     *              orElseThrow()默认值是给的一个错误.... 如果 此Optional为空的 就报给的错误;
     * */
    @Test
    public void orElseThrowOptional() {

        Optional<String> nameOptional = Optional.of("小白");
        String name = nameOptional.orElse("小黑");
        System.out.println(name);//小白
        String orElseName = (String) nameOptional.map(s -> { //这里把nameOptional置为空的Optional实例
            return null;
        }).orElseThrow(() -> {
            return new RuntimeException("此Optional为空的,在orElseThrow方法报错 ");
        });
        System.out.println(orElseName);
    }
}



2.10 toString:返回当前实例的 String 形式

  • Optional 重写了Object 的 toString() 方法;

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {


   
    /*
     * 返回当前实例的 String 形式
     *       重写了 Object 的 toString() 方法
     * */
    @Test
    public void toStringOptional() {

        Optional<String> nameOptional = Optional.of("小白");
        System.out.println(nameOptional.toString());//Optional[小白]
        Optional<Integer> intOptional = Optional.of(12);
        System.out.println(intOptional.toString());//Optional[12]
        Optional<Object> nullOptional = ofNullable(null);
        System.out.println(nullOptional.toString());//Optional.empty
        Optional<Student> studentOptional = ofNullable(new Student("小白", 12));
        System.out.println(studentOptional.toString());//Optional[TestDemo.Student(name=小白, age=12)]
    }

}



2.11isPresent:判断 Optional 的值是否存在

  • 若Optional 存在值则返回 true, 否则返回 false.

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {

  /*
    * 判断 Optional 的值是否存在
    *       若存在返回 true, 否则返回 false.
    * */
    @Test
    public void isPresentOptional() {

        Optional<String> nameOptional = Optional.of("小白");
        boolean namePresent = nameOptional.isPresent();
        System.out.println(namePresent);//true
        Optional<String> stringOptional = nameOptional.filter(s -> s.equals("name")); //是否满足提供的谓词,不满足返回空的Optional
        System.out.println(stringOptional);//Optional.empty
        System.out.println(stringOptional.isPresent());//false
    }

}



2.12 ifPresentOrElse:如果值存在就执行指定的方法, 否则执行空值方法 【jdk版本9或以上】

  • 如果Optional的值存在就执行入参的第一个方法 否则就执行第二个方法

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {


   
    /*
    * 此方法是jdk版本9以及之后才有的
    *   如果Optional的值存在就执行指定的方法, 否则执行空值方法
    * */
    @Test
    public void ifPresentOrElseOptional() {
        Student student = new Student("小白", 12);
        Optional<Student> studentOptional = ofNullable(null); //todo(传个null测试 用来验证会不会执行空值方法)
//        studentOptional.ifPresentOrElse(s -> System.out.println("Optional值不是 Optional.empty 执行了notNullIfPresentOrElseOptional方法" + s), () -> System.out.println("Optional值为 Optional.empty 执行了nullIfPresentOrElseOptional方法"));
        studentOptional.ifPresentOrElse(this::notNullIfPresentOrElseOptional, this::nullIfPresentOrElseOptional);//Optional值为 Optional.empty 执行了nullIfPresentOrElseOptional方法
    }
    //当Optional值为 Optional.empty的时候执行
    private void nullIfPresentOrElseOptional() {
        System.out.println("Optional值为 Optional.empty 执行了nullIfPresentOrElseOptional方法");
    }
    //当Optional 不为 Optional.empty 执行
    private void notNullIfPresentOrElseOptional(Student student) {
        System.out.println("Optional值不是 Optional.empty 执行了notNullIfPresentOrElseOptional方法" + student);
    }

}



2.13 or:获取带值的 Optional, 如果 Optional 没有值则获得给定函数生成 Optional 【jdk版本9或以上】

  • 浅显易懂的意思就是 如果Optional 有值 就返回它本身,如果没值 就返回自定义的Optional

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {


    /*
    * 此方法是jdk版本9以及之后才有的
    *   获取带值的 Optional, 如果 Optional 没有值则获得给定函数生成 Optional.
    * */
    @Test
    public void orOptional() {
        Student student = new Student("小白", 12);
        Optional<Student> studentOptional = ofNullable(student);
        Optional<Student> orNotNullOptional = studentOptional.or(() -> ofNullable(new Student("小黑", 11)));
        System.out.println(orNotNullOptional); //Optional[TestDemo.Student(name=小白, age=12)]
        Optional<Student> orNullOptional = studentOptional.filter(s -> false).or(() -> ofNullable(new Student("小黑", 11)));
        System.out.println(orNullOptional);    //Optional[TestDemo.Student(name=小黑, age=11)]
    }
}




2.14 stream: 获取一个 Optional 的流 【jdk版本9或以上】

  • 链接: Java SE JDK8 之 stream流详解
  • 如果存在值则返回仅包含该值的顺序流(sequential Stream), 否则返回空流(empty Stream)

import org.junit.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static java.util.Optional.ofNullable;

public class OptionalTest {
    /*
    * 此方法是jdk版本9以及之后才有的
    *       获取一个 Optional 的流
    * */
    @Test
    public void streamOptional() {
        Student student = new Student("小白", 12);
        Optional<Student> studentOptional = Optional.ofNullable(student);
        Stream<Student> stream = studentOptional.stream();//从Optional转为stream流
        //转为stream 循环打印
        stream.forEach(s-> System.out.println(s));//TestDemo.Student(name=小白, age=12)
        studentOptional.filter(s->false).stream().forEach(System.out::println);//空 Stream 不会输出任何内容
    }
}








链接:Optional 类优雅解决空指针异常等操作详解 源代码下载地址

你可能感兴趣的:(JAVA,SE,java,javase)