jdk1.8 Optional类从入门到实战

简介: Optional 类是 Java 8 引入的一个容器类,用于表示一个值存在或不存在。其在 java.util 包中,主要目的是为了解决 Java 程序中广泛存在的空指针异常(NullPointerException)问题,同时提供了一种更优雅的方式来处理可能为 null 的对象。在 Java 8 之前,处理 null 值往往依赖于显式的 null 检查,这种方式不仅增加了代码的复杂度,而且容易出错。Optional 类提供了一种更好的解决方案,通过封装可能为 null 的值,强制开发者显式地处理值存在或不存在的情况,从而减少在运行时出现 NullPointerException 的可能性。

要深入了解和掌握 Java 8 的 Optional 类,可以分为几个步骤:从基础认识到实战应用,下面是一个分步指南:

1. 认识 Optional

首先,需要理解 Optional 是一个可以包含也可以不包含非null值的容器对象。这意味着 Optional 要么包含一个值,要么什么都不包含(即为空),但它绝不会包含一个 null 值。

2. 创建 Optional 对象

  • 使用 Optional.of(value) 创建:当你确定对象不为 null 时使用,如果 value 是 null,会立即抛出 NullPointerException
  • 使用 Optional.empty() 创建一个空的 Optional:表示不含任何值。
  • 使用 Optional.ofNullable(value) 创建:当你不确定对象是否为 null 时使用,如果 value 是 null,则创建一个空的 Optional 对象。

3. 访问 Optional 对象的值

  • 使用 isPresent() 检查是否有值:如果 Optional 包含值,返回 true;否则返回 false。
  • 使用 ifPresent(consumer) 执行代码块:如果存在值,则执行给定的操作,否则不做任何事情。
  • 使用 orElse(T other) 获取值:如果有值则将其返回,否则返回一个默认值。
  • 使用 orElseGet(Supplier<? extends T> other) 获取值:与 orElse 类似,但提供的是通过 Supplier 接口延迟计算的默认值。
  • 使用 orElseThrow(Supplier<? extends X> exceptionSupplier) 抛出异常:如果 Optional 为空,则抛出由指定的 Supplier 接口生成的异常。

4. 转换和过滤 Optional 对象

  • 使用 map(Function<? super T,? extends U> mapper) 转换值:如果 Optional 有值,则应用函数映射。
  • 使用 flatMap(Function<? super T,Optional<U>> mapper) 用于链式操作:如果有值,返回应用函数映射的结果,否则返回空的 Optional
  • 使用 filter(Predicate<? super T> predicate) 过滤值:如果值存在并且匹配给定的谓词,则返回包含该值的 Optional;否则返回一个空的 Optional

5. 实战应用

在实际应用中,Optional 特别适用于:

  • 作为方法的返回类型,避免返回 null 值。
  • 在Java Stream操作中,与 mapflatMap 等操作结合使用,进行复杂的数据转换和处理。
  • 作为更安全的替代方案,代替显式的 null 检查,减少代码中的 NullPointerException

示例代码

假设我们有一个可能返回 null 的方法,使用 Optional 可以这样改进:

java复制代码

public class User {
    private String name;

    // 假设这是一个可能返回 null 的方法
    public String getName() {
        return name;
    }

    // 使用 Optional 改进后的方法
    public Optional<String> getNameOpt() {
        return Optional.ofNullable(name);
    }
}

User user = new User();
// 传统方式,需要外部null检查
if(user.getName() != null){
    System.out.println(user.getName());
}
// 使用 Optional 的方式
user.getNameOpt().ifPresent(name -> System.out.println(name));

通过这个简单的转变,代码不仅更安全,而且可读性和维护性也得到了提升。开始使用 Optional 类,逐步摆脱 null 的困扰吧!

相关文章
|
7月前
|
安全 Java API
JDK 11中的动态类文件常量:探索Java字节码的灵活性与动态性
在JDK 11中,Java语言引入了一个新的特性,允许在运行时动态地修改类文件常量。这一特性为Java开发者提供了更大的灵活性,使他们能够根据需要在运行时更改类文件中的常量值。本文将深入探讨动态类文件常量的工作原理、优点、限制以及在实际项目中的应用。
162 11
|
3月前
|
Java Linux
java基础(3)安装好JDK后使用javac.exe编译java文件、java.exe运行编译好的类
本文介绍了如何在安装JDK后使用`javac.exe`编译Java文件,以及使用`java.exe`运行编译好的类文件。涵盖了JDK的安装、环境变量配置、编写Java程序、使用命令行编译和运行程序的步骤,并提供了解决中文乱码的方法。
77 2
|
4月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
1月前
|
安全 Java 开发者
AOP中的JDK动态代理与CGLIB动态代理:深度解析与实战模拟
【11月更文挑战第21天】面向切面编程(AOP,Aspect-Oriented Programming)是一种编程范式,它通过将横切关注点(cross-cutting concerns)与业务逻辑分离,以提高代码的可维护性和可重用性。在Java开发中,AOP的实现离不开动态代理技术,其中JDK动态代理和CGLIB动态代理是两种常用的方式。本文将从背景、历史、功能点、业务场景、底层逻辑等多个维度,深度解析这两种代理方式的区别,并通过Java示例进行模拟和比较。
45 4
|
3月前
|
Oracle Java 关系型数据库
CentOS 7.6操作系统部署JDK实战案例
这篇文章介绍了在CentOS 7.6操作系统上通过多种方式部署JDK的详细步骤,包括使用yum安装openjdk、基于rpm包和二进制包安装Oracle JDK,并提供了配置环境变量的方法。
295 80
|
3月前
|
Java API 开发者
【Java字节码操控新篇章】JDK 22类文件API预览:解锁Java底层的无限可能!
【9月更文挑战第6天】JDK 22的类文件API为Java开发者们打开了一扇通往Java底层世界的大门。通过这个API,我们可以更加深入地理解Java程序的工作原理,实现更加灵活和强大的功能。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来!
|
3月前
|
Java API 开发者
【Java字节码的掌控者】JDK 22类文件API:解锁Java深层次的奥秘,赋能开发者无限可能!
【9月更文挑战第8天】JDK 22类文件API的引入,为Java开发者们打开了一扇通往Java字节码操控新世界的大门。通过这个API,我们可以更加深入地理解Java程序的底层行为,实现更加高效、可靠和创新的Java应用。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来,并积极探索类文件API带来的无限可能!
|
4月前
|
存储 Java
【Java集合类面试七】、 JDK7和JDK8中的HashMap有什么区别?
JDK7中的HashMap使用数组加链表解决冲突,而JDK8增加了红黑树结构以优化链表过长时的性能,提高查找效率。
|
4月前
|
Oracle 安全 Java
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
|
4月前
|
Java 编译器 API
JDK版本特性问题之在 JDK 17 中,想声明一个密封类,如何解决
JDK版本特性问题之在 JDK 17 中,想声明一个密封类,如何解决