程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Java8新特性

    • Java8新特性简介
    • Lambda 表达式
    • 函数式接口
    • 方法的引用
    • 构造器和数组的引用
    • Stream 流式编程
    • 并行流与串行流
    • Optional 类的使用
      • 1. Optional 类概述
      • 2. Optional 类的常用方法
        • 2.1 创建 Optional 对象
        • 2.2 判断 Optional 是否包含值
        • 2.3 获取 Optional 容器中的值
      • 3. 实际开发中的使用场景
      • 4. 代码示例与详细解析
      • 5. 常见问题与解决方案
    • 对反射的支持增强
    • 接口中的默认方法与静态方法
    • 新时间日期API
    • Try-with-Resources 升级
    • 重复注解与类型注解
  • Java9新特性

  • Java10新特性

  • Java11新特性

  • Java12新特性

  • Java13新特性

  • Java14新特性

  • Java15新特性

  • Java新特性
  • Java8新特性
scholar
2024-08-24
目录

Optional 类的使用

# Optional 类的使用

前言

Optional 类是 Java 8 引入的一种用于解决空指针异常(NullPointerException)问题的容器类。它提供了一种优雅的方式来表示值的存在或不存在,并且避免了频繁的空值检查。

  • 1. Optional 类概述
  • 2. Optional 类的常用方法
    • 2.1 创建 Optional 对象
    • 2.2 判断 Optional 是否包含值
    • 2.3 获取 Optional 容器中的值
  • 3. 实际开发中的使用场景
  • 4. 代码示例与详细解析
  • 5. 常见问题与解决方案

# 1. Optional 类概述

  • Optional<T> 是一个容器类,可以包含类型为 T 的值,代表这个值存在。或者可以包含 null,表示这个值不存在。传统上,我们使用 null 来表示一个值不存在,而 Optional 可以更好地表达这个概念,并且能有效避免空指针异常。

# 2. Optional 类的常用方法

Optional 类提供了丰富的方法来简化空值的处理。以下是一些常用方法的介绍。

# 2.1 创建 Optional 对象

  • Optional.of(T value):创建一个非空的 Optional 实例,如果传入的值为 null,会抛出 NullPointerException。
  • Optional.empty():创建一个空的 Optional 实例。
  • Optional.ofNullable(T value):可以接受 null 值,如果值不为 null,则返回一个包含该值的 Optional;否则返回一个空的 Optional。

代码示例:

public class OptionalCreationExample {
    public static void main(String[] args) {
        // 创建一个非空的 Optional
        Optional<String> optional1 = Optional.of("Hello, World!");
        System.out.println(optional1.get()); // 输出:Hello, World!

        // 创建一个空的 Optional
        Optional<String> optional2 = Optional.empty();
        System.out.println(optional2.isPresent()); // 输出:false

        // 创建一个可接受 null 的 Optional
        Optional<String> optional3 = Optional.ofNullable(null);
        System.out.println(optional3.isPresent()); // 输出:false
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 2.2 判断 Optional 是否包含值

  • boolean isPresent():判断 Optional 中是否包含值,如果有值返回 true,否则返回 false。
  • void ifPresent(Consumer<? super T> action):如果 Optional 中包含值,则执行 Consumer 接口的实现代码,并且该值会作为参数传递给 action。

代码示例:

public class OptionalCheckExample {
    public static void main(String[] args) {
        Optional<String> optional = Optional.of("Hello, World!");

        // 判断是否有值
        if (optional.isPresent()) {
            System.out.println("Optional contains: " + optional.get());
        }

        // 使用 ifPresent() 方法
        optional.ifPresent(value -> System.out.println("Value is: " + value));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2.3 获取 Optional 容器中的值

  • T get():如果 Optional 中包含值,返回该值,否则抛出 NoSuchElementException。
  • T orElse(T other):如果 Optional 中有值则返回该值,否则返回指定的默认值。
  • T orElseGet(Supplier<? extends T> other):与 orElse 类似,但这里的默认值是通过 Supplier 接口生成的。
  • T orElseThrow(Supplier<? extends X> exceptionSupplier):如果 Optional 中有值则返回该值,否则抛出由 Supplier 接口提供的异常。

代码示例:

public class OptionalGetExample {
    public static void main(String[] args) {
        Optional<String> optional = Optional.ofNullable(null);

        // 使用 orElse() 方法提供默认值
        String result1 = optional.orElse("Default Value");
        System.out.println(result1); // 输出:Default Value

        // 使用 orElseGet() 方法提供默认值
        String result2 = optional.orElseGet(() -> "Generated Default Value");
        System.out.println(result2); // 输出:Generated Default Value

        // 使用 orElseThrow() 抛出异常
        try {
            String result3 = optional.orElseThrow(() -> new IllegalArgumentException("Value is missing"));
            System.out.println(result3);
        } catch (Exception e) {
            System.out.println(e.getMessage()); // 输出:Value is missing
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 3. 实际开发中的使用场景

Optional 的应用场景非常广泛,特别是在处理可能为 null 的数据时。例如,在从数据库中获取用户信息或从外部 API 获取数据时,通常会涉及到空值处理。Optional 提供了一种更加优雅和安全的处理方式。

案例:使用 Optional 处理可能为空的对象属性

假设我们有一个 Boy 类,它可能包含一个 Girl 对象。我们要获取 Girl 对象的名字,传统方式需要进行多次空值检查,而使用 Optional 可以更加简洁。

传统方式:

public String getGirlName(Boy boy) {
    if (boy != null) {
        Girl girl = boy.getGirl();
        if (girl != null) {
            return girl.getName();
        }
    }
    return "Default Name";
}
1
2
3
4
5
6
7
8
9

使用 Optional 的方式:

public String getGirlName(Boy boy) {
    return Optional.ofNullable(boy)
                   .map(Boy::getGirl)
                   .map(Girl::getName)
                   .orElse("Default Name");
}
1
2
3
4
5
6

在上面的例子中,Optional 让我们能够以链式的方式处理可能为空的属性,避免了多层嵌套的 if 语句。

# 4. 代码示例与详细解析

完整代码示例:

public class OptionalUsageExample {
    public static void main(String[] args) {
        // 测试非空对象
        Boy boy1 = new Boy(new Girl("Alice"));
        System.out.println(getGirlName(boy1)); // 输出:Alice

        // 测试空对象
        Boy boy2 = new Boy(null);
        System.out.println(getGirlName(boy2)); // 输出:Default Name

        // 测试空 Boy 对象
        Boy boy3 = null;
        System.out.println(getGirlName(boy3)); // 输出:Default Name
    }

    public static String getGirlName(Boy boy) {
        return Optional.ofNullable(boy)
                       .map(Boy::getGirl)
                       .map(Girl::getName)
                       .orElse("Default Name");
    }
}

class Boy {
    private Girl girl;

    public Boy(Girl girl) {
        this.girl = girl;
    }

    public Girl getGirl() {
        return girl;
    }
}

class Girl {
    private String name;

    public Girl(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

详细解析:

  • Optional.ofNullable(boy):首先检查 boy 是否为空,如果为空则返回空的 Optional。
  • map(Boy::getGirl):如果 boy 不为空,获取 Boy 中的 Girl 对象。
  • map(Girl::getName):继续获取 Girl 的名字,如果任意一步为空,则跳过剩余的操作。
  • orElse("Default Name"):如果最终没有获取到名字,则返回默认值 "Default Name"。

# 5. 常见问题与解决方案

  1. 什么时候应该使用 Optional?

    • Optional 适用于方法返回值的场景,特别是可能返回 null 的情况。它不应该用于实体类的属性或者方法参数。
  2. Optional 是否可以代替所有的空值检查?

    • Optional 提供了一种更优雅的空值处理方式,但在某些性能敏感的场景下,需要权衡是否使用它。尤其是在频繁创建大量对象时,可能会带来额外的开销。

通过合理使用 Optional,可以让代码更加简洁、可读性更强,同时也减少了潜在的空指针异常风险。

编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
并行流与串行流
对反射的支持增强

← 并行流与串行流 对反射的支持增强→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式