终结 Java 空指针异常!优雅方案解析与案例演示

2023-10-29

目录

⭐️引言

⭐️产生原因

⭐️优雅解析

⭐️代码示例

        优雅解决方案一:条件判断

        优雅解决方案二:断言与异常处理

        优雅解决方案三:使用 Objects 类的 requireNonNull 方法

        优雅解决方案三:Optional 类的妙用

⭐总结


⭐️引言

        NullPointerException(空指针异常)是 Java 开发者经常遇到的问题,它通常由于访问或操作一个空对象引起。本文将详细介绍如何优雅地识别、解析和处理这个问题。

⭐️产生原因

详解导致 NullPointerException 的主要原因:

  • 对空对象的属性或方法调用
  • 未初始化的变量使用
  • 数组未初始化访问
  • 返回值为 null 的方法调用 

⭐️优雅解析

为了更好地解析和定位 NullPointerException,我们可以采取以下步骤:

  • 异常栈轨迹分析
  • 可能为空的变量逐一排查
  • 使用断言和条件检查
  • 利用 Optional 类来处理可能为空的值

⭐️代码示例

        优雅解决方案一:条件判断

        使用条件判断,避免对可能为 null 的对象进行操作,从而消灭潜在的空指针异常。

import java.util.Optional;

public class NPEElimination {
    public static void main(String[] args) {
        // 解决方案一:条件判断
        String name = null;
        if (name != null) {
            System.out.println("Hello, " + name + "!");
        }
    }

}

        这种写法是比较丑陋的,为了避免上述丑陋的写法,让丑陋的设计变得优雅。JAVA8提供了Optional类来优化这种写法,接下来的正文部分进行详细说明

      

       优雅解决方案二:断言与异常处理

        合理运用断言和异常处理机制,增强代码健壮性,避免空指针问题在代码中蔓延。

import java.util.Optional;

public class NPEElimination {
    public static void main(String[] args) {

        // 解决方案二:断言与异常处理
        String city = getCity();
        assert city != null : "City should not be null";
        System.out.println("City: " + city);

    }

    static String getCity() {
        return "New York";
    }

    static String getUsername() {
        return null;
    }
}

        优雅解决方案三:使用 Objects 类的 requireNonNull 方法

        利用 Java 7 引入的 Objects 类提供的 requireNonNull 方法,实现更简洁的空指针检查。

import java.util.Objects;

public class RequireNonNullExample {
    public static void main(String[] args) {
        String city = null;

        // 方案二:使用 requireNonNull 方法
        city = Objects.requireNonNull(city, "City should not be null");
        System.out.println("City: " + city);
    }
}

        优雅解决方案三:Optional 类的妙用

        解析 Optional 源码: Optional 类是 Java 8 引入的一个用于处理可能为 null 的值的容器。它提供了丰富的 API,如 of、ofNullable、isPresent、ifPresent、orElse 等方法,能够帮助开发者优雅地处理可能为空的值,避免繁琐的空指针检查。

通过深入阅读 Optional 类的源码,你可以掌握以下核心概念:

        1.内部属性:Optional 内部维护一个 value 属性,可以是实际的非空值,也可以是 null。

        在 Optional 类中,value 属性是用于保存实际的非空值或者 null 的。该属性的类型为泛型 T,表示可以保存任意类型的值。

        源码解析: value 属性在 Optional 类中是一个 final 修饰的字段,用于保存实际的值。当 Optional 对象包含一个非空值时,value 属性将引用该值;当 Optional 对象为空时,value 属性为 null

以下是 Optional 类中的部分源码,展示了 value 属性的定义和初始化:

public final class Optional<T> {

    // 实际的值,可以是非空值或者 null
    private final T value;

    // 构造方法,用于创建包含非空值的 Optional
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

    // 构造空的 Optional
    private Optional() {
        this.value = null;
    }

    // ...
}

        使用案例: 以下是一个示例,演示如何使用 Optionalvalue 属性来存储实际的非空值或者 null

import java.util.Optional;

public class ValueAttributeExample {
    public static void main(String[] args) {
        String name = "John";

        // 创建包含非空值的 Optional
        Optional<String> optionalName = Optional.of(name);
        if (optionalName.isPresent()) {
            System.out.println("Name: " + optionalName.get()); // 输出:Name: John
        }

        // 创建空的 Optional
        Optional<String> emptyOptional = Optional.empty();
        if (!emptyOptional.isPresent()) {
            System.out.println("Empty Optional"); // 输出:Empty Optional
        }
    }
}
  1. of 和 ofNullable 方法:用于创建 Optional 对象,其中 of 方法要求传入非空值,而 ofNullable 方法可以接受可能为空的值。

        Optional 类中的 ofofNullable 方法是用于创建 Optional 对象的两种方式,它们分别对应于传入非空值和可能为空的值。让我们深入了解它们的源码和使用案例。

        源码解析: ofofNullable 方法在 Optional 类中是静态方法。它们用于创建包含指定值的 Optional 对象,其中 of 方法要求传入非空值,而 ofNullable 方法可以接受可能为空的值。

以下是 Optional 类中的部分源码,展示了 ofofNullable 方法的定义和实现:

public final class Optional<T> {

    // 静态方法,创建包含指定非空值的 Optional
    public static<T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    // 静态方法,创建包含指定值(可能为空)的 Optional
    public static<T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

    // ...
}

        使用案例: 以下是一个示例,演示如何使用 ofofNullable 方法来创建不同类型的 Optional 对象:

import java.util.Optional;

public class OfAndOfNullableExample {
    public static void main(String[] args) {
        String name = "John";

        // 使用 of 创建包含非空值的 Optional
        Optional<String> optionalName = Optional.of(name);
        if (optionalName.isPresent()) {
            System.out.println("Name: " + optionalName.get()); // 输出:Name: John
        }

        // 使用 ofNullable 创建包含可能为空的 Optional
        String nullValue = null;
        Optional<String> nullableOptional = Optional.ofNullable(nullValue);
        if (!nullableOptional.isPresent()) {
            System.out.println("Value is null"); // 输出:Value is null
        }
    }
}
  1. isPresent 方法:判断 Optional 对象是否包含非空值。
  2. ifPresent 方法:在包含非空值的情况下,执行传入的操作。
public final class Optional<T> {
    //省略....
    public boolean isPresent() {
        return value != null;
    }
    //省略...
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }
}
 Optional.ofNullable(user)
    .ifPresent(u->{
        dosomething(u);
});
  1. orElse 方法:在 Optional 为空时,返回一个默认值。

   orElse 方法是 Optional 类中常用的一个方法,用于在 Optional 为空时返回一个默认值。这可以有效地处理可能为空的情况,避免了空指针异常。

        源码解析: orElse 方法的源码很简单,它接受一个参数作为默认值,如果 Optional 对象为空,则返回传入的默认值。

以下是 Optional 类中的部分源码,展示了 orElse 方法的定义和实现:

public final class Optional<T> {

    // 返回值或默认值
    public T orElse(T other) {
        return value != null ? value : other;
    }

    // ...
}

        使用案例: 以下是一个示例,演示如何使用 orElse 方法来处理可能为空的 Optional,并提供一个默认值:

  1. filter 和 map 方法:用于对 Optional 内的值进行过滤和映射。
public final class Optional<T> {
    //省略....
   Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
}

使用案例如下:

Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);
  1. flatMap 方法:用于处理嵌套的 Optional,降低 Optional 嵌套层次。
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

使用案例如下:

 // 使用 flatMap 处理嵌套的 Optional
        String result = optionalBook.flatMap(Book::getAuthorName)
                                   .orElse("Unknown Author");
  1. 空 Optional:Optional.empty() 表示空的 Optional。

        源码解析: flatMap 方法的源码定义在 java.util.Optional 类中,其签名如下:

public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

flatMap 方法接受一个函数 mapper,该函数将原始 Optional 的值映射为另一个 Optional,然后将嵌套的 Optional 展平为一个单层的 Optional。如果原始 Optional 为空,或者 mapper 映射的 Optional 为空,那么 flatMap 返回一个空的 Optional

        使用案例: 假设我们有一个场景,要从一本书的 Optional 中获取作者的名字,而作者的名字也被包装在一个 Optional 中。使用 flatMap 方法可以简洁地处理这种情况。

下面是一个示例代码,演示如何使用 flatMap 方法处理嵌套的 Optional

import java.util.Optional;

class Book {
    private String authorName;

    public Book(String authorName) {
        this.authorName = authorName;
    }

    public Optional<String> getAuthorName() {
        return Optional.ofNullable(authorName);
    }
}

public class FlatMapExample {
    public static void main(String[] args) {
        Book book = new Book("John Doe");
        Optional<Book> optionalBook = Optional.of(book);

        // 使用 flatMap 处理嵌套的 Optional
        String result = optionalBook.flatMap(Book::getAuthorName)
                                   .orElse("Unknown Author");

        System.out.println("Author: " + result);
    }
}

⭐总结

        通过本文的精彩演绎,你将彻底掌握解决 Java 空指针异常的多种优雅方法,在生产环境中我们可以通过Sonar 代码检测工具来检测代码问题,暴露出空指针所在位置,深入理解 Optional API 的精髓,助力你的代码更加健壮、可靠,从而成为更出色的 Java 开发者。

                                                            ⏳  名言警句:说会的,说对的
                                                            ✨ 原创不易,还希望各位大佬支持一下
                                                           

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

终结 Java 空指针异常!优雅方案解析与案例演示 的相关文章

  • Spring控制器是线程安全的吗

    我遇到了这个控制器示例 想知道它是否是线程安全的 我特别想知道 gson 实例变量 import org springframework stereotype Controller import org springframework we
  • 检查双精度值的等于和不等于条件

    我在比较两者时遇到困难double values using and 我创建了 6 个双变量并尝试进行比较If健康 状况 double a b c d e f if a b c d e f My code here in case of t
  • Java 创建浮雕(红/蓝图像)

    我正在编写一个 Java 游戏引擎 http victoryengine org http victoryengine org 并且我一直在尝试生成具有深度的 3D 图像 您可以使用那些红色 蓝色眼镜看到 我正在使用 Java2D 进行图形
  • 无法加载 jar 文件的主类

    我使用 Eclipse IDE 开发了一个应用程序 创建应用程序后 我以 jar 格式导出项目 当我尝试运行此 jar 文件时 出现错误 无法加载主类 请帮忙 当您将项目导出为 jar 时 请参阅此所以问题 https stackoverf
  • 通过 InjectMocks Spy 注入对象

    我需要对一个类运行一系列单元测试 该类具有 Autowired Logger 实现 实现的基本思想是 Mock Logger logger InjectMocks TestedClass tested 但我想保存日志输出功能 Mockito
  • Java 泛型/类型调度问题

    考虑以下程序 import java util List import java util ArrayList public class TypeTest public static class TypeTestA extends Type
  • 如何解决 onEditCommit 事件上的类型不匹配错误?

    我在 Fxml 中使用 onEditCommit 事件在用户编辑数据后检索数据 FXML 代码
  • Java 重写 hashCode() 得到 StackOverflowError

    所以我不太熟悉重写 hashCode 并且我似乎在 hashCode 方法中以某种方式进行了一些无限递归 这是我的场景 我有一个 DuplicateCache 类 它是一个缓存对象 用于检查系统中的重复对象 我有一个静态内部类 Duplic
  • Java:从元素创建 DOM 元素,而不是文档

    如您所知 在 Java 中创建 Dom 元素的正确方法是执行以下操作 import org w3c dom Document import org w3c dom Element Document d Element e e d creat
  • spring - 强制 @Autowired 字段的 cglib 代理

    我有混合堆栈 EJB 和 Spring 为了将 Spring 自动装配到 EJB 我使用SpringBeanAutowiringInterceptor 不确定这是否会影响我遇到的问题 在尝试通过以下方式自动装配 bean 时 Scope p
  • Java替换特定字符

    这是我在这个网站上的第一个问题 所以我会尽量不要成为一个十足的菜鸟 我目前正在用java 创建刽子手游戏 所以我问你的问题是我们是否被赋予了 幽灵 这个词 并将 Ghost 替换为 hiddenWord ghost length for i
  • 尝试在没有 GatewayIntent 的情况下访问消息内容

    我希望每当我写一条打招呼的消息时 机器人都会在控制台中响应一条消息 但它只是给我一个错误 JDA MainWS ReadThread WARN JDA Attempting to access message content without
  • 参数动态时如何构建 JPQL 查询?

    我想知道是否有一个好的解决方案来构建基于过滤器的 JPQL 查询 我的查询太 富有表现力 我无法使用 Criteria 就像是 query Select from Ent if parameter null query WHERE fiel
  • 打印包含 JBIG2 图像的 PDF

    请推荐一些库 帮助我打印包含 JBIG2 编码图像的 PDF 文件 PDFRenderer PDFBox别帮我 这些库可以打印简单的 PDF 但不能打印包含 JBIG2 图像的 PDF PDFRenderer尝试修复它 根据 PDFRedn
  • 如何在keycloak中动态编辑standalone.xml文件

    我正在尝试通过 docker 编辑standalone xml 并尝试添加 但 keycloak 正在使用它standalone xml 但我可以看到standalone xml 文件中的更改 我需要在standalone xml 文件中添
  • ExceptionHandler 不适用于 Throwable

    我们的应用程序是基于 Spring MVC 的 REST 应用程序 我正在尝试使用 ExceptionHandler 注释来处理所有错误和异常 I have ExceptionHandler Throwable class public R
  • 来自客户端的超时 Web 服务调用

    我正在使用 RestEasy 客户端调用网络服务 一项要求是 如果调用运行时间超过 5 秒 则中止 超时调用 我如何使用 RestEasy 客户端实现这一目标 我只看到服务器端超时 即如果在一定时间内未完成请求 Rest Easy 网络服务
  • struts 教程或示例

    我正在尝试在 Struts 中制作一个登录页面 这个想法是验证用户是否存在等 然后如果有错误 则返回到登录页面 错误显示为红色 典型的登录或任何表单页面验证 我想知道是否有人知道 Struts 中的错误管理教程 我正在专门寻找有关的教程 或
  • 使用 eclipse IDE 配置 angularjs

    我想开始使用 AngularJs 和 Java Spring 进行开发 我使用 Eclipse 作为 IDE 我想配置我的 Eclipse 以使这些框架无缝工作 我知道我可能要求太多 但相信我 我已经做了很多研究 你们是我最后的选择 任何帮
  • 尝试使用带有有效购买令牌的 Java Google Play Developer API v3 检索应用内购买信息时出现错误请求(无效值)

    当使用 Java Google Play Developer API 版本 3 并请求有效购买令牌的购买信息时 我收到以下异常 API 调用返回 400 Bad Request 响应以及以下消息 code 400 errors domain

随机推荐

  • 关机对话框字体大小不跟随显示设置变化的修改

    现象描述 设置 显示 显示大小 最大 按电源键的关机 弹出确认框 android 12中原生去掉了关机确认对话框的的显示 但是客户头铁非要显示 询问MTK回答客制代码只能自己解决 只能自己搞定 贴了代码 仅供参考 在ShutdownThre
  • 普通文件下载 + 前端获取后端返回的文件流并下载

    参考资料 前端接受后端文件流并下载的几种方法 ajax 请求二进制流 图片 文件 XMLHttpRequest 请求并处理二进制流数据 之最佳实践 ajax请求二进制流进行处理 ajax异步下载文件 response setHeader 的
  • JavaScript的学习笔记

    JavaScript的学习笔记 学习B站上狂神的视频记录的笔记 1比较运算符 console log 1 1 true 判断的时候值相等 类型不同也是true console log 1 1 false 值相等且类型相同 才为true 2严
  • arcgis 字段计算器 条件赋值_ARCGIS中字段计算器的使用说明

    Field Calculator 工具可以在属性表字段点击右键 选择 Field Calculator 或者Data Management Tools gt fields gt Calculate Field打开 1 基本函数 针对数值型
  • 谷歌开发者工具之功能面板

    Network 面板 用的最多的面板 可查看 Ajax 请求 页面访问时间线等等 Performance 面板 查看JS性能 详情可看我的另一篇文章 如何使用谷歌浏览器开发者工具中的Performance分析网页性能 Rendering 面
  • 华为OD机试 - 恢复数字序列(Python)

    题目描述 对于一个连续正整数组成的序列 可以将其拼接成一个字符串 再将字符串里的部分字符打乱顺序 如序列8 9 10 11 12 拼接成的字符串为89101112 打乱一部分字符后得到90811211 原来的正整数10就被拆成了0和1 现给
  • C#中List常用方法:判断存在、查找、排序

    项目常用List来进行数据操作管理 有一些方法经常百度 所以这里记录下 目录 1 List判断元素是否存在 返回bool 2 List查找 返回对象 3 List排序 4 对象属性打印 5 List 其他方法 1 List判断元素是否存在
  • 程序员的自我修养——链接,装载与库

    章节目录 静态链接 编译和链接 目标文件 静态链接 windows COFF 装载和动态链接 可执行文件的装载与进程 动态链接 Linux共享库的组织 Windows下的动态链接 库与运行库 内存 运行库 系统调用与API 运行库实现 一
  • 【C++入门】引用符&详解

    1 C 的 引用符介绍 1 符号在C语言中表示取地址运算 2 C 对 符号进行拓展 符号新增了引用的用法 3 声明引用时 必须同时对其进行初始化 4 引用声明完毕后 相当于目标变量有两个名称 引用名就相当于变量的别名 操作引号名就相当于操作
  • 【深度解析→博文总结】李宏毅机器学习2023作业02Classification(Framewise Phoneme Prediction)

    文章目录 系列文章 简要说明 视频分享 作业详情 调参记录 Simple Baseline 0 49798 Medium Baseline 0 66440 Stong Baseline 0 74944 Boss Baseline 0 830
  • html制作电影界面,电影网站界面设计HTML_CSS模板

    实例简介 简单生活 希望对大家有用 要觉得本资源有价值请分享给您的朋友 生活就是人来人往 分享越多 收获越多 作者 天天ASP家园 实例截图 核心代码 7c828d9e b4a1 48fc be7b 81a2137edae2 电影网站界面设
  • ​​​​​​​三个案例帮你彻底了解反馈电路中的相位补偿

    转自于http www elecfans com d 669847 html 三个案例帮你彻底了解反馈电路中的相位补偿 2004年 帮朋友做镍氢充电器 利用镍氢电池充满电时电压有一个微小的下降这个特点来识别是否已经充满 比如1 2V的镍氢电
  • 程序员戴耳机究竟在听什么,看完真相,我惊了!

    今天 某妹子突然凑到我的耳边轻声说说 我们公司的程序员 清一色的戴着耳机 你说他们是不是故意不想听我们提的需求 我很方 因为我也喜欢戴耳机 思考ing 思考了一秒钟后 一本正经的和妹子说 你这么漂亮 怎么会呢 戴耳机可能只是他们的习惯罢了
  • String详解

    String类的理解 什么是String类 String类实现了Serializable接口 对象可以被序列化 序列化之后 对象可以进行网络传输 或者持久化 String类实现的Comparable接口 对象可以比较大小 String类实现
  • GoLang之搭建Web服务器

    2014 02 05 wcdj 0 摘要 之前总结过如何使用Perl搭建Web服务 Web服务器的实现 最小的Perl Web服务器 本文介绍如何使用GoLang搭建Web服务 Go语言提供了一个完善的net http包 通过这个http包
  • 将yolov3.pth转换为onnx并进行推理

    前言 最近训练了一个yolov3检测模型 需要将保存好的 pth文件转换为onnx并且写一个inference过程 于是学习了一下onnx的知识并记录下来 用到的工具 onnx 安装方法 pip install onnx onnxrunti
  • DVI-A、DVI-D、DVI-I接口定义、DVI接口图和DVI接口标准介绍

    dvi接口义 DVI接口图片 DVI接口标准介绍 dvi hdmi接口定义 DVI 的定义 DVI A 就是与 VGA 规范一样的 包括 RGBHV 信号线的模拟接口 RGB 是什么不用赘述了吧 HV 分别是水平 和 垂直 扫描的 行同步
  • springboot集成log4j日志

    一 新建log4j properties配置文件 配置内容如下 log4j rootLogger CONSOLE info error DEBUGlog4j rootLogger info error CONSOLE DEBUGlog4j
  • 端口扫描

    常见的扫描类型有以下几种 秘密扫描 秘密扫描是一种不被审计工具所检测的扫描技术 它通常用于在通过普通的防火墙或路由器的筛选 filtering 时隐藏自己 秘密扫描能躲避IDS 防火墙 包过滤器和日志审计 从而获取目标端口的开放或关闭的信息
  • 终结 Java 空指针异常!优雅方案解析与案例演示

    目录 引言 产生原因 优雅解析 代码示例 优雅解决方案一 条件判断 优雅解决方案二 断言与异常处理 优雅解决方案三 使用 Objects 类的 requireNonNull 方法 优雅解决方案三 Optional 类的妙用 总结 引言 Nu