一、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());
}
}
}
三、问题描述
- 预期行为 :
calculateSum方法应正确计算两个数的和并返回结果,即使其中一个参数为null,也应按照业务逻辑处理,而不是抛出空指针异常。 - 实际行为 :当传入的
num1为null时,程序抛出NullPointerException。这是因为在 Java 中,当对包装类(如Integer)进行算术运算时,会发生自动拆箱,即将包装类转换为基本数据类型。在上述代码中,num1 + num2时,num1会自动拆箱为int类型。然而,null无法转换为基本数据类型,因此抛出空指针异常。尽管代码表面上看起来只是简单的加法运算,但由于自动拆箱机制,隐藏了潜在的空指针风险。
四、解决方案
- 显式空值检查:在进行运算之前,对可能为空的包装类进行显式的空值检查。
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;
}
}
- 使用
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);
}
}