一个由泛型和Auto Unbox引发的Crash
来源:互联网 发布:有关大数据的例子 编辑:程序博客网 时间:2024/04/30 10:27
出了个神奇的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
- 一个由泛型和Auto Unbox引发的Crash
- 由Looper引发的crash及Looper源代码笔记
- 由一个问题引发的思考
- 由一个#符号引发的一系列问题
- 一个由PING引发的思考
- 由一个贴子引发的讨论
- 由一个面试题引发的思考
- 一个由字符集引发的血案
- 一个由数组越界引发的。。。
- 一个由sizeof引发的问题
- 一场由一个s引发的郁闷
- 由一个线程例子引发的思考
- 一个由CountDownLatch引发的Bug
- 一个由session.close()引发的血案
- 由一个stack OOM引发的血案
- 由一个函数引发的改进思考
- 一个由正则表达式引发的血案
- 一个由API level引发的惨案
- 1095. Cars on Campus (30)
- hdu 3709 Balanced Number 2010成都区域赛 数位dp
- ffmpeg for android error
- centos 6.6升级自带mysql版本文档
- 安装RPM套件rpm-build错误解决:NOKEY、elfutils is needed
- 一个由泛型和Auto Unbox引发的Crash
- AVPlayer 和 MPMoivePlayerController的区别
- 机器学习基石学习笔记3 VC Dimension(1)
- 解决Win10 Windows10关键错误 开始菜单和Cortana无法工作问题
- 1096. Consecutive Factors (20)
- 【剑指offer】面试题6:重建二叉树
- ipvsadm 安装配置
- win7 64位上VM虚拟机安装64位Ubuntu14.04.3
- 正则表达式匹配x相对