【Java基础教程】(三十一)常用类库篇 · 第一讲:Optional类——解锁Java的Optional操作,消灭那些隐匿的空指针,还程序世界一个安稳!~

这篇具有很好参考价值的文章主要介绍了【Java基础教程】(三十一)常用类库篇 · 第一讲:Optional类——解锁Java的Optional操作,消灭那些隐匿的空指针,还程序世界一个安稳!~。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【Java基础教程】(三十一)常用类库篇 · 第一讲:Optional类——解锁Java的Optional操作,消灭那些隐匿的空指针,还程序世界一个安稳!~,# Java基础教程,java,开发语言,数据库,后端,java-ee,jvm

1️⃣ 概念

Optional 类是Java 8引入的新特性,旨在解决空值(null)的处理问题。它的设计目的是为了提供一种更好的方式来处理可能为空的值,避免使用null导致空指针异常。

Optional是一个容器对象,可以持有某个类型的非空值或者空值。它是一个包装类,用于替代可能为空的引用变量。

下面是Optional类的几个特征:

  • Optional 可以持有非空的值或空值;
  • 通过一系列方法,可以对 Optional对象进行操作和转换;
  • Optional 提供了一套简洁的API,方便进行空值处理。

2️⃣ 优势和缺点

优点

  • 提高代码的可读性和可维护性,明确表达值可能为空的语义;
  • 强制开发人员显式地处理空值情况,避免了空指针异常。

缺点

  • 可能引入一些额外的代码复杂性,增加代码量。

3️⃣ 使用

3.1 常用操作API

Java的Optional使用流程如下:

  1. 创建Optional对象:

    • 使用Optional.ofNullable(value)创建一个Optional对象,并将value作为包装值,value可以是null
    • 使用Optional.of(value)创建一个Optional 对象,并将 value作为包装值,value不能为null,否则会抛出NullPointerException
  2. 判断Optional对象是否包含值:

    • 使用optional.isPresent()方法判断 Optional 对象是否包含非空值。
      - 使用optional.isEmpty()方法判断Optional对象是否为空。
  3. 获取Optional对象的值:

    • 使用optional.get()方法获取对象中的值。如果Optional对象包含值,返回该值;否则抛出NoSuchElementException异常。
  4. 使用默认值:

    • 使用optional.orElse(defaultValue)方法获取Optional对象的值。如果对象包含值,则返回该值;否则返回指定的默认值。
    • 使用optional.orElseGet(supplier)方法获取Optional对象的值。如果对象包含值,则返回该值;否则使用供应商函数生成一个值并返回。
  5. 条件过滤:

    • 使用optional.filter(predicate)方法根据条件过滤 Optional对象。匹配的话返回当前对象,否则返回空的Optional对象。
  6. 转换值类型:

    • 使用optional.map(mapper)方法将Optional 对象中的值转换为mapper函数的结果,并返回新的对象。
    • 使用optional.flatMap(mapper)方法类似 map操作,但是返回的是 mapper函数所返回的Optional对象本身。
  7. 其他常用方法:

    • 使用optional.ifPresent(consumer)方法,如果Optional对象包含值,则执行传入的操作。
    • 使用optional.orElseThrow()方法,获取Optional对象的值,如果Optional对象包含值,则返回该值;否则抛出NoSuchElementException异常。

在使用Optional 时,应根据具体场景选择合适的方法进行操作。在链式调用中,可以通过一系列的 Optional 操作来进行连续、安全和可读性更高的调用流程,处理可能为空的值。

此外,使用Optional 还需要注意谨慎使用get()方法获取对象的值,最好使用更安全的方法如ifPresentorElse等进行值的处理,以避免空指针异常的发生。

Java的 Optional类中全部的操作方法API汇总如下表:

方法名 说明
boolean isPresent() 判断Optional对象是否包含值。如果Optional对象包含非空值,返回true;否则返回false
ifPresent(Consumer<? super T> consumer) 如果Optional对象包含值,则执行传入的操作
T get() 如果Optional对象包含值,返回该值;否则抛出NoSuchElementException异常
T orElse(T other) 获取Optional对象的值,若不存在则返回默认值other
T orElseGet(Supplier<? extends T> other) 获取Optional对象的值,若不存在则使用提供的Supplier生成一个新值并返回
T orElseThrow() 获取Optional对象的值,若不存在则抛出NoSuchElementException异常
Optional filter(Predicate<? super T> predicate) 如果Optional对象包含值且满足条件,则返回当前Optional对象;否则返回空的Optional对象
map(Function<? super T, ? extends U> mapper) 对Optional对象中的值进行映射操作,返回新的Optional对象
flatMap(Function<? super T, Optional> mapper) 类似map操作,但返回的是mapper函数所返回的Optional对象本身

3.2 案例

下面是一个Java案例程序,演示了如何使用上述每个方法:

import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class OptionalExample {
    public static void main(String[] args) {
        // 定义字符串
        String value1 = "Hello, world!";
        String value2 = null;

        // 1、创建Optional对象,并将字符串作为包装值
        Optional<String> optional1 = Optional.ofNullable(value1);
        Optional<String> nullOpt = Optional.ofNullable(value2);
        
        // 2、创建Optional对象,并将字符串作为包装值。注意这种方式下,value不能为null,否则会抛出NullPointerException
        Optional<String> optional2 = Optional.of("Hello, Java!");
        //value为null,会抛出NullPointerException
        try {
            nullOpt = Optional.of(value2);
        }catch (NullPointerException e){
            System.out.println(e);
        }

        // 3、创建一个空的Optional对象
        Optional<String> optional = Optional.empty();
        System.out.println("\n" + optional);
        
        // 4、判断Optional对象是否包含非空值
        System.out.println("\nIs optional1 present? " + optional1.isPresent());
        System.out.println("Is nullOpt present? " + nullOpt.isPresent());
        
        // 5、获取Optional对象中的值,如果不存在则抛出NoSuchElementException异常
        String result1 = optional1.get();
        System.out.println("\nValue of optional1: " + result1);
        try {
            String tempResult = nullOpt.get();
            System.out.println("Value of nullOpt: " + tempResult);
        }catch (NoSuchElementException e){
            System.out.println(e);
        }

        // 6、获取Optional对象的值,若不存在则返回指定的默认值
        String result2 = optional2.orElse("Default Value");
        System.out.println("\nValue of optional2: " + result2);
        String defaultResult = nullOpt.orElse("Default Value");
        System.out.println("Value of nullOpt: " + defaultResult);

        // 7、获取Optional对象的值,若不存在则使用提供的Supplier生成一个新值
        Supplier<? extends String> other = () -> "Generated Value";
        String result3 = optional2.orElseGet(other);
        System.out.println("\nValue of optional2: " + result3);
        String generatedResult = nullOpt.orElseGet(other);
        System.out.println("Value of nullOpt: " + generatedResult);
        
        // 8、根据条件过滤Optional对象,返回满足条件的Optional对象
        Predicate<? super String> predicate = s -> s.length() > 10;
        Optional<String> filteredOptional = optional1.filter(predicate);
        System.out.println("\nFiltered optional1: " + filteredOptional);
        filteredOptional = nullOpt.filter(predicate);
        System.out.println("Filtered nullOpt: " + filteredOptional);
        
        // 9、将Optional对象中的值转换为mapper函数的结果,并返回新的Optional对象
        Optional<Integer> lengthOptional = optional1.map(String::length);
        System.out.println("\nLength of optional1: " + lengthOptional.orElse(0));
        
        // 10、类似map操作,返回的是mapper函数所返回的Optional对象本身
        Optional<String> flatMappedOptional = optional1.flatMap(s -> Optional.of(s.toUpperCase()));
        System.out.println("\nFlattened and mapped optional1: " + flatMappedOptional.orElse(""));
        
        // 11、如果Optional对象包含值,则执行传入的操作
        System.out.println();
        optional2.ifPresent(System.out::println);

        // 12、获取Optional对象的值,若不存在则抛出自定义的异常
        try {
            String result = optional.orElseThrow(() -> new Exception("Exception: Value is not present"));
            System.out.println("\nValue of optional: " + result);
        }catch (Exception e) {
            System.out.println("\n" + e.getMessage());
        }
    }
}

运行结果如下:

java.lang.NullPointerException

Optional.empty

Is optional1 present? true
Is nullOpt present? false

Value of optional1: Hello, world!
java.util.NoSuchElementException: No value present

Value of optional2: Hello, Java!
Value of nullOpt: Default Value

Value of optional2: Hello, Java!
Value of nullOpt: Generated Value

Filtered optional1: Optional[Hello, world!]
Filtered nullOpt: Optional.empty

Length of optional1: 13

Flattened and mapped optional1: HELLO, WORLD!

Hello, Java!

Exception: Value is not present

3.3 使用技巧

使用Optional 时可以考虑以下几点优化技巧:

  1. 尽量不要在方法参数或返回类型中使用 OptionalOptional主要用于局部变量和字段,以表明其可能为空;
  2. 尽量避免使用optional.get()方法获取 Optional 对象的值,可以使用ifPresent()orElse()等更安全的方法来处理值的情况;
  3. 谨慎使用嵌套Optional,避免过度复杂化逻辑。

4️⃣ 应用场景

常见的应用场景包括:

  • 避免null处理:Optional可以使得代码更加清晰明确,避免因为忽略处理空值而导致空指针异常;
  • 方法返回值:用于替代可能为空的返回值,以便提供更好的可读性;
  • 链式调用:通过一系列的Optional操作,可以进行连续且安全的调用链。

结合实际生产应用来说,Optional在以下业务场景可以发挥重要的作用:

  • 处理外部API调用,当返回值可能为空时使用Optional来封装;
  • 解析JSON对象时,若某些字段为可选字段,可使用Optional来处理;
  • 在数据库查询中,如果结果可能为空,可以使用Optional处理。

5️⃣ 实现原理

Optional类是一个常规的、泛型化的类,通过包装值的方式来处理可能为空的情况。它采用了一些与空对象模式相关的思想,Optional类提供了一组丰富的操作方法,以便更方便地处理可选值,避免了使用空对象时的空指针异常。

Optional类的设计灵感之一可以类比为空对象模式(Null Object Pattern)。
在空对象模式中,需要处理某个操作的对象可能为空,而使用空对象作为代替,以避免空指针异常。
对于Optional类来说,当value字段为null时,表示该Optional对象为空,它也被视作特殊的空对象。

Optional类内部有一个私有字段value,用于存储包装的值。value字段的类型是泛型T,即可以是任何类型的值。如果Optional对象包含一个非空值,则value字段存储这个值;如果Optional对象为空,则value字段为null。

🌾 总结

Optional类是Java 8引入的强大工具,用于解决空值处理问题。它可以用于包装可能为空的引用,提供一种更优雅且可读性更高的方式来表示和处理可能为空的值。使用Optional类,我们可以明确表达值是可空的,并通过一系列简单的操作方法来避免潜在的空指针异常。

尽管Optional并不适用于所有情况,但在正确的场景下,它可以大大提高代码的可读性和可维护性。然而,需要谨慎使用Optional,避免过度使用,以免引入额外的复杂性。了解Optional的基础和高级语法、Java操作API以及实现原理等方面的知识,将有助于正确地应用和优化Optional,从而编写更稳健的Java代码。


温习回顾上一篇(点击跳转)《【Java基础教程】(三十)Java新特性篇 · 第十讲: Stream流——释放流式编程的效率与优雅,狂肝万字只为透彻讲清 Stream流!~》

继续阅读下一篇(点击跳转)《【Java基础教程】(三十二)常用类库篇 · 第二讲:包装类 Wrapper Class——概念及用途, 自动装箱与拆箱,常用操作方法~》
文章来源地址https://www.toymoban.com/news/detail-606004.html

【Java基础教程】(三十一)常用类库篇 · 第一讲:Optional类——解锁Java的Optional操作,消灭那些隐匿的空指针,还程序世界一个安稳!~,# Java基础教程,java,开发语言,数据库,后端,java-ee,jvm

到了这里,关于【Java基础教程】(三十一)常用类库篇 · 第一讲:Optional类——解锁Java的Optional操作,消灭那些隐匿的空指针,还程序世界一个安稳!~的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java基础教程】(三十七)常用类库篇 · 第七讲:日期时间处理类——三万字全面讲解 LocalDateTime和 DateTimeFormatter,Date、Calendar ~

    Java的时间处理相关类主要是为了提供灵活、可靠地处理日期和时间的能力,以满足各种应用程序中对时间的需求。这些类旨在简化日期和时间的操作,并提供一致的方法和功能来处理时间上的计算、格式化和解析。 🔍 时间日期及处理类汇总 将Java中所有用于表示日期时间的

    2024年02月16日
    浏览(55)
  • 【Java练习题汇总】《第一行代码JAVA》Java常用类库篇,汇总Java练习题——Optional类、包装类、可变字符串支持类、Runtime类、System类、数学运算类、日期时间处理...

    一、填空题 在 java.lang 包中提供了两个字符串类,分别是________ 和________ 。这两个类都是________ 接口的子类,字符串类提供的求字符串长度的方法是________________ 。 Java 提供的两个大数操作类是________ 和________ 。 对象克隆方法是________ 类提供的,方法名称是________________ ,对

    2024年02月16日
    浏览(54)
  • 【JavaSE】Java基础语法(三十一):可变参数

    可变参数介绍 可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了 方法的参数类型已经确定,个数不确定,我们可以使用可变参数 可变参数定义格式 可变参数的注意事项 这里的变量其实是一个数组 如果一个方法有多个参数,包含可变参数,可

    2024年02月08日
    浏览(56)
  • 第四十一天 Java基础学习(三十五)

    一、JSP内置对象 ●内置对象 因为SP的本质是Servlet,在JSP文件经过转译之后,生成JAVA代码,在运行时JSP给我们准备好了九个可以直接使用而不用我们自己去new的对象,这九个对象我之为内置对象. 内置对象完全由SP自行去维护,我们直接使用即可。 ●九大内置对象 confia ;page ;

    2024年02月16日
    浏览(46)
  • 【Java零基础入门篇】第 ⑦ 期 - 常用类库

    博主:命运之光 专栏:Java零基础入门   学习目标 掌握Java各种常用类库的使用方法。 目录 Java类库 字符串String String 概述 创建字符串对象的2种方式 String类的特点 创建字符串对象的2种方式 总结:创建字符串对象的2种方式区别 字符串的比较 字符串的比较 String类其它常用

    2024年02月04日
    浏览(36)
  • 【前端知识】React 基础巩固(三十一)——Redux的简介

    概念 纯函数(确定的输入一定产生确定的输出,函数在执行过程中不产生副作用): 在程序设计中,若一个函数符合以下条件,那么这个函数就被称为纯函数 此函数在相同的输入值时,需产生相同的输出 函数的输出和输入值以外的其他隐藏信息或状态无关,也和由I/O设备产

    2024年02月16日
    浏览(53)
  • ElasticSearch7.3学习(三十一)----Logstash基础学习

    一、Logstash基本介绍 Logstash 是一个功能强大的工具,可与各种部署集成。 它提供了大量插件,可帮助你解析,丰富,转换和缓冲来自各种来源的数据(文件、数据库......)。logstash简单来说就是一个 数据抽取工具 ,将数据从一个地方转移到另一个地方。 Logstash 是 Elastic 栈非

    2023年04月09日
    浏览(34)
  • Java常用类库与技巧

    序号 地址 1 计算机网络核心 2 数据库相关 3 Redis 4 Linux相关 5 JVM的内容 6 GC相关的 7 Java多线程与并发 8 Java多线程与并发-原理 9 Java常用类库与技巧 10 Java框架-Spring 1、String,StringBuffer,StringBuilder的区别? 2、Java异常 异常处理机制主要回答了三个问题 What:异常类型回答了什么

    2024年02月10日
    浏览(39)
  • Hadoop3教程(三十一):(生产调优篇)异构存储

    异构存储,也叫做冷热数据分离 。其中,经常使用的数据被叫做是热数据,不经常使用的数据被叫做冷数据。 把冷热数据,分别存储在不同的存储介质里,从而达到对每个介质的利用率最高,从而实现整体最佳性能,或者说性价比更高(比如说高性能硬盘放经常使用的数据

    2024年02月08日
    浏览(43)
  • vue 3 第三十一章:状态管理(Pinia基础知识)

    状态管理是现代 Web 应用开发中的一个重要概念。Vue 3 中的状态管理库 Pinia ,是一个基于 Vue 3 Composition API 的状态管理库,它提供了一种 简单 、 灵活 的方式来管理应用程序的状态,同时还具有 高性能 和 可扩展性 。 Pinia 在某种程度上来说,也可以被叫做 Vuex5 ,因为它结合

    2024年02月07日
    浏览(99)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包