当前位置: 首页 > news >正文

【最佳实践】优雅地处理 Java 中的空指针

Optional 类是随着 Java 8 在 2014 年引入的。它是 java.util 包中的一个容器类,主要用于解决 Java 中长期存在的空指针异常(NullPointerException, NPE)问题。

可能是Java 8 Optional最佳实践_28天写作_ES_her0_InfoQ写作社区

优雅地处理 Java 中的空指针:使用 Optional 简化链式调用

每一层都和上一层是分离的,到下一层只需要知道:你是谁,你要做什么?

在日常开发中,避免空指针异常(NullPointerException, NPE)是 Java 开发者们常见的挑战之一。我们经常会遇到这样的问题:当需要访问嵌套对象的属性时,如果对象中某个字段为空,就会导致程序崩溃。传统的解决方案是使用多层嵌套的 if 判断来确保每一层对象都不为空。然而,随着代码的复杂性增加,这种方法不仅繁琐,而且难以维护。

C# 中有一种操作符 ?. 可以简化这种链式调用,它允许开发者轻松地访问对象深层次的属性,而不必每次都去检查中间对象是否为 null。在 Java 中,虽然没有直接类似 ?. 的操作符,但是我们可以通过 Optional 类来实现相似的功能,并且保持代码的优雅性与可读性。

传统方式处理空指针

假设我们有一个 User 对象,其中可能包含一个 Address 对象,而 Address 对象中可能有一个 City 对象。现在,我们希望获取用户所在城市的名称。使用传统的 if 方式,我们的代码可能会如下所示:

if (user != null) {Address address = user.getAddress();if (address != null) {City city = address.getCity();if (city != null) {return city.getName();}}
}
return "Unknown";

虽然这种写法能够避免 NPE,但显然层层嵌套的 if 判断非常臃肿,代码的可读性较差。而且如果对象的层次更多,这种写法将变得更加不可维护。

使用 Optional 优雅地处理链式调用

为了解决上面的问题,我们可以使用 Java 8 中引入的 Optional 类。Optional 提供了一种更优雅的方式来处理可能为 null 的对象,避免了大量的 null 检查,同时让代码更加简洁清晰。下面我们来看如何用 Optional 来优化上述代码:

return Optional.ofNullable(user).map(User::getAddress).map(Address::getCity).map(City::getName).orElse("Unknown");

相比传统的写法,使用 Optional 让我们可以通过 map 方法在每一层调用中进行空值检查。如果对象不存在,链式调用会在对应的层级停止,最终返回 orElse 中定义的默认值。在这个例子中,如果 useraddresscity 任意一个为空,最终都会返回 "Unknown"

解析 Optional 写法的优点
  1. 简洁:通过链式调用的方式避免了嵌套的 if 语句,使代码简洁易读。
  2. 安全:每次通过 map 进行对象的获取时,Optional 会自动进行空值检查,不再需要手动编写 null 判断逻辑。
  3. 可维护性:代码结构清晰,扩展和维护更加方便。如果以后需要增加新的属性检查,只需继续添加 map 方法即可。
可扩展的使用场景

Optional 不仅适用于简单的对象属性获取,还可以用于处理复杂的数据转换或返回默认值的场景。举个例子,如果我们想在获取城市名称的同时确保所有字符小写展示,也可以通过链式调用来处理:

return Optional.ofNullable(user).map(User::getAddress).map(Address::getCity).map(City::getName).map(String::toLowerCase).orElse("unknown");

在现代 Java 开发中,使用 Optional 来处理可能为 null 的对象,是一种非常优雅且推荐的实践。通过链式调用的方式,我们可以避免冗长的 null 检查逻辑,使代码更加简洁和安全。Optional 的使用不仅提高了代码的可读性,还能减少 NPE 引发的程序崩溃问题。如果你还没有将 Optional 融入到日常开发中,不妨尝试一下,体验更加优雅的代码编写方式。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【java系】记录一次ClassLoader.getResourceAsStream获取不到文件流
  • Linux上使用touch修改文件时间属性的限制
  • Unity同时启动多个Editor
  • 项目管理必备3大工具,助你的项目管理技能飞跃提升。
  • Git提交有乱码
  • ChatGPT 为何将前端框架从 Next.js 更换为 Remix以及框架的选择
  • WIFI | 硬件 基于MT7988D平台VC5772实现BE7200路由设计方案
  • 计算机组成原理(笔记3)
  • FEAD:fNIRS-EEG情感数据库(视频刺激)
  • CS61C 2020计算机组成原理Lecture03
  • 【Kubernetes】(K8S)彻底卸载详细教程
  • Spring Boot中的响应与分层解耦架构
  • vue3 自定义el-tree树形结构样式
  • Nginx+Tomcat(负载均衡、动静分离)
  • python毕业设计基于django+vue医院社区医疗挂号预约综合管理系统7918h-pycharm-flask
  • FastReport在线报表设计器工作原理
  • flutter的key在widget list的作用以及必要性
  • IP路由与转发
  • java 多线程基础, 我觉得还是有必要看看的
  • JavaScript 一些 DOM 的知识点
  • Java深入 - 深入理解Java集合
  • Koa2 之文件上传下载
  • Laravel核心解读--Facades
  • LeetCode算法系列_0891_子序列宽度之和
  • python docx文档转html页面
  • Python_OOP
  • React的组件模式
  • Sublime text 3 3103 注册码
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 阿里云Kubernetes容器服务上体验Knative
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 坑!为什么View.startAnimation不起作用?
  • 爬虫模拟登陆 SegmentFault
  • 前嗅ForeSpider中数据浏览界面介绍
  • 少走弯路,给Java 1~5 年程序员的建议
  • 微服务框架lagom
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 怎么将电脑中的声音录制成WAV格式
  • puppet连载22:define用法
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ![CDATA[ ]] 是什么东东
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • $.ajax,axios,fetch三种ajax请求的区别
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (第一天)包装对象、作用域、创建对象
  • (二开)Flink 修改源码拓展 SQL 语法
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (一) springboot详细介绍
  • (转)nsfocus-绿盟科技笔试题目
  • (转)Oracle存储过程编写经验和优化措施
  • .bat批处理(四):路径相关%cd%和%~dp0的区别