c语言 空指针异常处理,深究“HashMap在进行put操作时出现的空指针异常”

本文详细记录了一次排查Java程序中HashMap空指针异常的过程。通过假设和调试,确定问题出在从Redis获取的HashMap为null,导致后续put操作引发异常。修复方案是在put操作前检查HashMap是否为null并进行初始化。此外,文章还探讨了类型转换、装箱拆箱以及Map的put方法的工作原理,强调了在使用HashMap时需要注意的细节。
摘要由CSDN通过智能技术生成

示例代码:

HashMap redisMap = new HashMap<>();

RMap hashMap = redissonComponent.getMap(ORDER_REFUND_RECORD_SNAPSHOT);

redisMap = (HashMap) hashMap.get(model.getManagerId().toString());

redisMap.put(model.getId(), refundType);

### 一、上述代码在运行过程中偶发空指针异常,在看到日志抛错的时候我试想了可能出现的几种情况: ###

假设1.model.getId()抛出异常,Id这个参数为null

假设2.Id或者refundType中存在数据类型为int的情况,与map中声明的Integer的数据类型不符

假设3.赋值后的redisMap为null,使之前初始化的redisMap没有生效

### 二、接下来进入debug模式 ###

debug1.首先debug到第四行,观察到id与refundType二者皆有值,且数据类型均为Integer,因此可以排除掉假设1和假设二。

debug2.接着debug到第二行,发现程序从Redis中获取到的hashMap为null,理所应当的是,debug到第三行代码的时候,redisMap的结果也为null,那么此时基本可以断定假设3是正确的。

### 三、如何解决此次问题 ###

修正代码

HashMap redisMap = new HashMap<>();

RMap hashMap = redissonComponent.getMap(ORDER_REFUND_RECORD_SNAPSHOT);

redisMap = (HashMap) hashMap.get(model.getManagerId().toString());

if (ObjectUtils.isEmpty(redisMap)) {

redisMap = new HashMap<>();

}

redisMap.put(model.getId(), refundType);

根据上面的debug2,我在redisMap第一次赋值后加入了逻辑判断,如果redisMap被赋予了null值,就需要重新对redisMap进行初始化,并**分配内存**。

修正代码后,程序运行中没有再次出现空指针异常。此时我可以得出结论:

1.HashMap如果只初始化而不为其分配内存,在进行put操作时,会出现空指针异常。

2.HashMap在初始化且分配内存后,如果对其进行赋予null的操作,接着进行put操作时,依然会出现空指针异常。

### 四、知识扩展 ###

最后回顾一下解决问题的思路,首先我假设了三种出现此类问题的情况,其次去程序中进行调试,最后给出解决方案。

作为知识的扩展,我们回到假设2,为什么我会做如此假设呢?

1.如果我们put的数据是int类型,此时会有一个装箱的过程,也就是调用Integer的静态方法valueOf,将int装箱为Integer。

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)

return IntegerCache.cache[i + (-IntegerCache.low)];

return new Integer(i);

}

2.执行map的put方法

public V put(K key, V value) {

return putVal(hash(key), key, value, false, true);

}

可以看到put方法其实是有返回值的,只不过我们通常不会在意它。如果当前put的key的value在put之前,map里面是存在的,那么就返回之前已经存在的value对象,如果不存在那么就返回null。

这里我们要注意:**Map里面只能存放对象,不能存放基本类型,例如int,需要使用Integer。**

3.由于当前int类型的值是初次put,map里是不存在对应的value的,那么此时返回的Integer对象肯定是null。此时需要为put方法的返回值赋值,那么就需要对Integer对象执行拆箱操作。

Integer拆箱操作

public int intValue() {

return value;

}

此时返回的Integer对象是null,执行拆箱操作肯定就会报空指针异常了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值