java中的Optional
在 Java 8 中,Optional
是一个用于处理可能为 null
的值的容器类,旨在减少空指针异常(NullPointerException
)并提升代码的可读性。以下是 Optional
的核心用法和最佳实践:
1. 创建 Optional
对象
1.1 常规创建方式
-
Optional.of(T value)
创建一个包含非空值的Optional
。如果传入null
,会抛出NullPointerException
。Optional<String> name = Optional.of("Alice");
-
Optional.ofNullable(T value)
允许传入null
,若值为null
,返回空的Optional
。Optional<String> nullableName = Optional.ofNullable(getName()); // 若 getName() 返回 null,nullableName 为空
-
Optional.empty()
创建一个空的Optional
。Optional<String> empty = Optional.empty();
2. 访问 Optional
中的值
2.1 检查值是否存在
-
isPresent()
判断Optional
是否包含值。if (name.isPresent()) {System.out.println("值存在: " + name.get()); }
-
ifPresent(Consumer<? super T> consumer)
如果值存在,执行传入的操作。name.ifPresent(n -> System.out.println("值存在: " + n));
-
isEmpty()
(Java 11+)
判断Optional
是否为空。if (empty.isEmpty()) {System.out.println("Optional 为空"); }
2.2 安全获取值
-
get()
直接获取值,但需确保值存在(否则抛出NoSuchElementException
)。String result = name.get(); // 若 name 为空,抛出异常
-
orElse(T other)
若值存在返回该值,否则返回默认值。String defaultName = nullableName.orElse("Default Name");
-
orElseGet(Supplier<? extends T> supplier)
与orElse()
类似,但默认值由Supplier
延迟生成。String generatedName = nullableName.orElseGet(() -> "Generated Name");
-
orElseThrow(Supplier<? extends X> exceptionSupplier)
若值不存在,抛出指定异常。String actualName = nullableName.orElseThrow(() -> new IllegalArgumentException("值不存在"));
3. 转换与过滤 Optional
中的值
3.1 map(Function<? super T, ? extends U> mapper)
对 Optional
中的值进行转换,返回新的 Optional
。
Optional<String> upperCaseName = name.map(String::toUpperCase);
upperCaseName.ifPresent(System.out::println); // 输出: ALICE
3.2 flatMap(Function<? super T, Optional<U>> mapper)
用于处理嵌套的 Optional
,避免嵌套结构。
Optional<Optional<String>> nested = Optional.of(name);
Optional<String> flattened = nested.flatMap(o -> o); // 展平为 Optional<String>
3.3 filter(Predicate<? super T> predicate)
根据条件过滤值,若条件不满足,返回空的 Optional
。
Optional<String> longName = name.filter(n -> n.length() > 5);
longName.ifPresent(System.out::println); // 若 name 为 "Alice"(长度 5),不输出
4. 链式操作示例
结合 map
、filter
和 orElse
实现链式调用:
Optional<User> user = getUser();
String city = user.map(User::getAddress).map(Address::getCity).orElse("Unknown City");
System.out.println("城市: " + city);
5. Optional
的最佳实践
✅ 推荐做法
-
方法返回值处理
当方法可能返回null
时,返回Optional<T>
而不是null
。public Optional<User> findUserById(String id) {// ... }
-
链式操作替代嵌套判断
用map
和flatMap
替代多层if-else
。// 传统方式 User user = getUser(); if (user != null) {Address address = user.getAddress();if (address != null) {System.out.println(address.getCity());} }// 使用 Optional Optional.ofNullable(user).map(User::getAddress).map(Address::getCity).ifPresent(System.out::println);
-
提供默认值
使用orElse
或orElseGet
处理缺失值。String name = Optional.ofNullable(user).map(User::getName).orElse("Guest");
⚠️ 常见误区
-
不要用
Optional
声明类字段
Optional
不适合用作类的字段,因为序列化和反序列化可能存在问题。// ❌ 不推荐 private Optional<String> name;
-
避免滥用
get()
直接调用get()
前必须检查值是否存在。// ❌ 错误 String name = optional.get(); // ✅ 正确 String name = optional.orElseThrow(() -> new RuntimeException("值不存在"));
-
不要过度使用
Optional
仅在明确“值可能缺失”的场景使用,避免过度设计。// ❌ 不推荐 public Optional<String> getName() { ... }// ✅ 推荐 public String getName() { return Optional.ofNullable(...).orElse(""); }
6. Optional
与 Stream
的结合
Optional
可以与 Stream
结合使用,处理集合中的空值:
List<Optional<String>> optionalNames = ...;
List<String> names = optionalNames.stream().filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
7. 总结
方法 | 用途 | 示例 |
---|---|---|
of | 创建非空的 Optional | Optional.of("Hello") |
ofNullable | 创建允许为 null 的 Optional | Optional.ofNullable(getName()) |
isPresent | 检查值是否存在 | optional.isPresent() |
ifPresent | 若存在则执行操作 | optional.ifPresent(System.out::println) |
orElse | 提供默认值 | optional.orElse("Default") |
map | 转换值 | optional.map(String::toUpperCase) |
flatMap | 展平嵌套的 Optional | optional.flatMap(o -> o) |
filter | 过滤值 | optional.filter(s -> s.length() > 5) |
orElseThrow | 若无值则抛出异常 | optional.orElseThrow(() -> new RuntimeException("无值")) |
通过合理使用 Optional
,可以显著减少空指针异常的风险,同时使代码更简洁、意图更明确。
相关文章:
java中的Optional
在 Java 8 中,Optional 是一个用于处理可能为 null 的值的容器类,旨在减少空指针异常(NullPointerException)并提升代码的可读性。以下是 Optional 的核心用法和最佳实践: 1. 创建 Optional 对象 1.1 常规创建方式 Op…...
Qt事件循环机制
受事件循环机制影响,按钮的样式表改变了可能不会立即刷新。 需要使用 update() 或 repaint() 或者调用 QApplication::processEvents() 强制处理所有待处理的事件,从而确保界面更新。 在 Qt 中,事件循环(Event Loop)是…...
深入理解 OAuth 2.0:技术核心与实战场景
在互联网应用日益复杂的今天,如何安全、高效地实现第三方应用授权访问资源,成为开发者面临的重要问题。OAuth 2.0 凭借其灵活、安全的授权机制,成为解决这一问题的主流方案。本文将深入剖析 OAuth 2.0 的技术重点,并结合具体使用场…...
Rust 环境变量管理秘籍:从菜鸟到老鸟都爱的 dotenv 教程
前言 写代码的你,是否遭遇过这些灵魂拷问: “我现在在哪个环境?开发?测试?还是直接在生产线上裸奔?”“少写一个 .env,测试脚本在数据库里上演清空大法,客户当场破防。”“每次手动设置 RUST_ENV,命令敲到一半就开始怀疑人生,还怕输错一个字符引发灭世级事故。”别慌…...

CSS经典布局之圣杯布局和双飞翼布局
目标: 中间自适应,两边定宽,并且三栏布局在一行展示。 圣杯布局 实现方法: 通过float搭建布局margin使三列布局到一行上relative相对定位调整位置; 给外部容器添加padding,通过相对定位调整左右两列的…...

OpenCV 的 CUDA 模块中用于将多个单通道的 GpuMat 图像合并成一个多通道的图像 函数cv::cuda::merge
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 OpenCV 的 CUDA 模块中,cv::cuda::merge 函数用于将多个单通道的 GpuMat 图像合并成一个多通道的图像。该函数是 cv::merge 的 GP…...

计网实验笔记(一)CS144 Lab
Lab0 ByteStream : 实现一个在内存中的 有序可靠字节流Lab1 StreamReassembler:实现一个流重组器,一个将字节流的字串或者小段按照正确顺序来拼接回连续字节流的模块Lab2 TCPReceiver:实现入站字节流的TCP部分。Lab3 TCPSender:实…...
Blog Contents
目录 Python Financing Medical Logistics Tool(IT & AI) 持续更新~ Python # Name URL 1 Python | Dashboard制作 Python | Dashboard制作-CSDN博客 2 Python | AKShare获取A股数据 Python | AKShare获取A股数据-CSDN博客 3 Python | A股指标对比 Python | A股…...

什么是ERP?ERP有哪些功能?小微企业ERP系统源码,SpringBoot+Vue+ElementUI+UniAPP
什么是ERP? ERP翻译过来叫企业资源计划,通俗的讲,应该叫企业的全面预算控制,其通常包括三个部分:工程预算、投资预算和经营预算(即产销存预算)。之所以做预算控制,是因为企业运作的…...

dockerfile: PaddleOCR hubserving api 服务
前言 目前 OCR 有比较成熟的方案,想着直接通过 docker 部署一个提供 api 接口服务,查看了一些开源方案,最终发现还是 PaddleOCR 比较好用。 本篇不介绍 PaddleOCR 的详细使用方式,只介绍一下构建镜像的 dockerfile 需要注意的事…...
【速写】TRL:Trainer的细节与思考(PPO/DPO+LoRA可行性)
序言 问题缘起来自发现PPOTrainer里并没有跟SFTTrainer类似的peft_config参数,而SFTTrainer在带和不带peft_config参数的情况下分别对应高效微调和全量微调。自然就会想到是否可以把PPO和PEFT结合,但是目前peft包和trl包上似乎还是存在这种兼容性的问题…...

Vue3+uniapp 封装axios
1.第一步在项目根目录新建utils文件夹,里边新建两个文件request.js和uni-api-promisify.js 2.request.js 代码 要安装axios import axios from axios import { showToast } from /utils/uni-api-promisify// 创建axios实例 const service axios.create({baseURL:…...

QEMU模拟32位ARM实现自定义系统调用
实现自定义系统调用 如何使用 QEMU 模拟32位 ARM 环境参考:使用Qemu模拟32位ARM系统 修改linux内核源码 使用 linux-4.4.240 源码,下载链接:下载链接 在 arch\arm\include\uapi\asm\unistd.h 文件下新增系统调用 sys_test: /…...

MySQL——数据类型表的约束
目录 数据类型 数值类型 tinyint类型 bit类型 float类型 decimal类型 字符类型 char类型 varchar类型 日期和时间类型 选择类型 表的约束 null default comment zerofill primary key auto_increment unique key foreign key 数据类型 在MySQL中的数据类…...

# YOLOv2:目标检测的升级之作
YOLOv2:目标检测的升级之作 在目标检测领域,YOLO(You Only Look Once)系列算法以其高效的速度和创新的检测方式受到了广泛关注。今天,我们就来深入探讨一下 YOLOv2,看看它是如何在继承 YOLOv1 的基础上进行…...

【爬虫】DrissionPage-1
官网地址:DrissionPage官网 小需求采集,我喜欢,我要学。 1 介绍 这是用python编写的爬虫自动化工具,将Selenium 和 Requests 的功能巧妙地整合在一起,提供了统一又简单的操作接口。开发者可以在浏览器模式࿰…...

Oracle OCP认证考试考点详解083系列15
题记: 本系列主要讲解Oracle OCP认证考试考点(题目),适用于19C/21C,跟着学OCP考试必过。 71. 第71题: 题目 解析及答案: 关于在 Oracle 18c 及更高版本中基于 Oracle 黄金镜像的安装,以下哪…...
java刷题基础知识
List<int[]> merged new ArrayList<int[]>(); return merged.toArray(new int[merged.size()][]); 表示一个存储 int[] 类型元素的列表,list灵活支持扩展,因为不知道最后有几个区间,所以用list,最后toArray返回成数组…...

部署大模型:解决ollama.service: Failed with result ‘exit-code‘的问题
起因是这样: Loaded: loaded (/etc/systemd/system/ollama.service; disabled; preset: enabled) Active: activating (auto-restart) (Result: exit-code) since Tue 2025-05-13 19:31:19 CST; > Process: 12272 ExecStart/usr/bin/ollama serve (codeexited, status1/FAI…...
阿克曼-幻宇机器人系列教程2- 机器人交互实践(Topic)
在上一篇文章中,我们介绍了两种登录机器人的方式,接下来我们介绍登录机器人之后,我们如何通过topic操作命令实现与机器人的交互。 1. 启动 & 获取topic 在一个终端登录树莓派后,执行下列命令运行机器人 roslaunch huanyu_r…...

Spring AI 开发本地deepseek对话快速上手笔记
Spring AI Spring AI是一个旨在推进生成式人工智能应用程序发展的项目,Spring AI的核心目标是提供高度抽象化的组件,作为开发AI应用程序的基础,使得开发者能够以最少的代码改动便捷地交换和优化功能模块 在开发之前先得引入大模型…...

SpringBoot中的拦截器
SpringBoot中的拦截器 Filter 典型场景 全局鉴权/接口耗时统计 WebFilter("/*") public class CostFilter implements Filter {Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {long start System.currentTimeMill…...
Spark,IDEA编写Maven项目
以下是在IDEA中使用Maven构建Spark项目的步骤: 一、环境准备 1. 安装JDK - 确保IDEA配置了JDK 8(推荐11)。 2. 安装Maven - 配置Maven环境变量,IDEA中设置Maven路径( File > Settings > Build > Maven &#…...

半小时快速入门Spring AI:使用腾讯云编程助手CodeBuddy 开发简易聊天程序
引言 随着人工智能(AI)技术的飞速发展,越来越多的开发者开始探索如何将AI集成到自己的应用中。人工智能正在迅速改变各行各业的工作方式,从自动化客服到智能推荐系统,AI的应用几乎无处不在。Spring AI作为一种开源框架…...

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】金融风控分析案例-10.3 风险指标可视化监控
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 PostgreSQL金融风控分析之风险指标可视化监控实战一、引言二、案例背景三、数据准备(一)数据来源与字段说明(二)数据清洗 四、…...
数学复习笔记 6
前言 复习一下行列式的一些基本的题。感觉网课有点没跟上了。今天花点时间跟上网课的进度。要紧跟进度,然后剩下的时间再去复习前面的内容。多复习,提升自己的解题能力。 行列式和矩阵 三年级,我现在是三年级下册。。。马上就要结束大学的…...
微服务的“导航系统”:使用Spring Cloud Eureka实现服务注册与发现
在上一篇中,我们理解了微服务架构的核心理念以及Spring Cloud为我们提供的强大工具集。我们提到,微服务架构的一个核心挑战在于,服务实例的网络位置是动态的,服务之间需要一种机制来互相定位。 想象一下,你开了一家新…...

geoserver发布arcgis瓦片地图服务(最新版本)
第一步:下载geoserver服务,进入bin目录启动 需要提前安装好JDK环境,1.8及以上版本 安装完成,页面访问端口,进入控制台界面,默认用户名密码admin/geoserver 第二步:下载地图 破解版全能电子地图下载器&…...

多边形,矩形,长方体设置
在cesium中,我们可以通过既有的库来进行对地图的构建 // 向场景中添加一个几何体(立方体) scene.primitives.add(new Cesium.Primitive({// 定义几何体实例geometryInstances: new Cesium.GeometryInstance({// 使用BoxGeometry.fromDimensions方法创建…...
Spring Boot 框架概述
1. 简介 Spring Boot 是由 Pivotal 团队开发的一个用于简化 Spring 应用开发的框架。它通过提供默认配置、嵌入式服务器和自动配置等特性,让开发者能够更快速地构建独立的、生产级别的 Spring 应用。 Spring Boot 的主要特点包括: 快速创建独立的 Spri…...