看似简单的空指针 —— 包装类自动拆箱陷阱

一、Bug 场景

在一个 Java 应用程序中,涉及到一些基本数据类型与包装类的操作。开发人员在处理业务逻辑时,认为代码逻辑清晰简单,但在特定情况下,程序却抛出了空指针异常(NullPointerException),导致程序崩溃,影响了业务功能的正常运行。

二、代码示例

业务逻辑类(有缺陷)

java 复制代码
public class BusinessLogic {
    public static int calculateSum(Integer num1, Integer num2) {
        // 预期是对两个数求和,忽略了包装类可能为空的情况
        return num1 + num2; 
    }
}

测试代码

java 复制代码
public class NullPointerBugExample {
    public static void main(String[] args) {
        Integer a = null;
        Integer b = 5;
        try {
            int result = BusinessLogic.calculateSum(a, b);
            System.out.println("计算结果: " + result);
        } catch (NullPointerException e) {
            System.out.println("捕获到空指针异常: " + e.getMessage());
        }
    }
}

三、问题描述

  1. 预期行为calculateSum 方法应正确计算两个数的和并返回结果,即使其中一个参数为 null,也应按照业务逻辑处理,而不是抛出空指针异常。
  2. 实际行为 :当传入的 num1null 时,程序抛出 NullPointerException。这是因为在 Java 中,当对包装类(如 Integer)进行算术运算时,会发生自动拆箱,即将包装类转换为基本数据类型。在上述代码中,num1 + num2 时,num1 会自动拆箱为 int 类型。然而,null 无法转换为基本数据类型,因此抛出空指针异常。尽管代码表面上看起来只是简单的加法运算,但由于自动拆箱机制,隐藏了潜在的空指针风险。

四、解决方案

  1. 显式空值检查:在进行运算之前,对可能为空的包装类进行显式的空值检查。
java 复制代码
public class BusinessLogic {
    public static int calculateSum(Integer num1, Integer num2) {
        if (num1 == null) {
            num1 = 0;
        }
        if (num2 == null) {
            num2 = 0;
        }
        return num1 + num2; 
    }
}
  1. 使用 Optional 类(Java 8+)Optional 类提供了一种更优雅的方式来处理可能为空的值。
java 复制代码
import java.util.Optional;

public class BusinessLogic {
    public static int calculateSum(Optional<Integer> num1Opt, Optional<Integer> num2Opt) {
        int num1 = num1Opt.orElse(0);
        int num2 = num2Opt.orElse(0);
        return num1 + num2; 
    }
}

测试代码调整为:

java 复制代码
import java.util.Optional;

public class NullPointerBugExample {
    public static void main(String[] args) {
        Optional<Integer> a = Optional.ofNullable(null);
        Optional<Integer> b = Optional.of(5);
        int result = BusinessLogic.calculateSum(a, b);
        System.out.println("计算结果: " + result);
    }
}
相关推荐
一木 之林16 分钟前
五、C++新特性、关键字与编译原理
java·jvm·算法
han_hanker20 分钟前
新手公司项目实战
java·maven
vHelios26 分钟前
【电商项目】商品搜索开发复盘(3):搜索与封装实现逻辑思考与编写
java
AI人工智能+电脑小能手44 分钟前
大白话说Java设计模式-37-中介者模式(源码剖析篇)
java·设计模式·线程池·中介者模式·源码分析·executor·applicationeventmulticaster
焦虑的说说1 小时前
虚拟线程浅析
java
摇滚侠1 小时前
《SpringBoot 3:入门与应用实战》第 7 章 AOP 思想与实现 阅读笔记 13
java·spring boot·笔记
Mr. zhihao1 小时前
线上卡顿排查决策手册:场景 × 命令 × 现象 × 调整方案
java·开发语言·jvm
FYKJ_20101 小时前
springboot网上购书商城---附源码15749
java·spring boot·后端·python·spark·django·php
LayZhangStrive1 小时前
Java IDEA - 各种快捷键设置汇总(提高工具使用效率)
java·idea·设置·快捷键