一个由泛型和Auto Unbox引发的Crash

出了个神奇的Crash,复盘一下:
public boolean foo(HashMap<String, Boolean> map){
...
return null != map && map.get("a_key");
}

这段代码居然有空指针,出在最后一行。这个空指针的原因还是很神奇的。
当“a_key”不在map中时,map会返回null。按照本屌的理解,实际调用的流程应该是:
boolean first = null != map;
if(first){
Object second = map.get("a_key"); //泛型里,类型擦除了
if(second instanceof Boolean){
return Boolean.valueOf(second);
}
}

实际上,大JVM的字节码是这样的:
...
#3 = Class #34 // java/lang/Boolean
...
21: invokevirtual #8 // Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;实际上真的是get了一个Object!果然是擦除了!
24: checkcast #3 // class java/lang/Boolean 貌似只有泛型的字节码里有这个调用,貌似,貌似
27: invokevirtual #9 // Method java/lang/Boolean.booleanValue:()Z 直接在get到的Object上invoke booleanValue!!!!!!所谓的auto unbox

擦除仅仅是在get的时候,检查了类型之后,直接将拿到的Object当做泛型对象使用,调用其上的booleanValue方法。这样就会有null.booleanValue()的调用出现,抛出空指针。
注意:Boolean.valueOf(obj)是不能解决这个问题的,因为get出来的对象会为了符合函数参数类型,进行一次unbox。

最后解决的办法:
Boolean val = null != map && map.get("a_key");//有checkcast,没有unbox
return null != val && val;//Boolean对象是可以为空的

Java字节码参考1 参考2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值