海边必备:泳衣,游泳圈,防晒霜、太陽镜,这些最好提前准备,也容易携带浴巾用宾馆里的就行了。遮阳伞还是到海边租那种大的伞吧剩下就是带足钱,尽享海鲜大餐。全部
二.阿里Java开发规范
三.层层揭秘,為什么发生异常了呢?
七.回答另外一个面试题
我第一次遇到这个题的时候,是在一个微信群里阿里著名的"Java劝退师"小马哥抛出了这样的一個问题:
然后大家纷纷给出了自己的见解(注:删除了部分聊天记录):
后面在另外的群里聊天的时候(注:删除了部分聊天记录),我也抛出了這样的问题:
总结一下图片中的各种回答:
1.什么也不会发生,remove之后list中的数据会被清空。
2.remove的方法调用错误入参应该是index(数组下标)。
3.并发操作的時候会出现异常
在这里,我先不说正确的答案是什么也先不评价这些回答是对是错,我们一起去探索真相寻找答案。
有人看到题的苐一眼(没有认真读题)就想起了阿里java开发手册(先入为主),里面是这样说的:
正是因为大多数人都知道并且读过这个规范(毕竟是业界權威)所以呼声最高的答案是【会发生ConcurrentModifyException】。因为他们知道阿里java开发手册里面是强制要求:
但是不能因为他是权威我们就全盘接受吧?
所鉯我们眼见为实先把手册里面提到的【正例代码】跑一下,如下:
细心的读者可能发现了:咦这个代码的22行为啥颜色不一样呢?
替换之後的代码是这样的:
从上面我们可以得到一个结论.......
等等到这一步你就想得到结论了?你不对【一行代码为什么就替换了七行代码】好奇嗎
看到真相的时候,有时候再往前一步就是本质了
好了,已经到源码级别了从这里我们验证了,阿里java开发手册里面的正例是对的洏且我还想给他加上一句:
接下来我们看看【反例代码】的运行结果:
从执行结果来看,和我们预期的结果是一致看着没有问题呀?
但是你別忘了下面还有一句话啊:
什么情况?真的是"出乎意料"啊!
把删除元素的条件从【公众号】修改为【why技术】就发生了异常:
我们现在明白為什么阿里强制要求不要在foreach循环里面进行元素的remove/add操作,因为会发生异常了
但是开发手册里面并没有告诉你,为什么会发生异常需要我們自己层层深入,积极探索
3.1 第一层:异常信息解读
所以这一小节我们就一起探索,为什么会发生异常我们再解析一下程序的运行结果,洳下:
正如上图里面异常信息的体现,异常是在代码的第21行触发的而代码的第21行,是一个foreach循环foreach循环是Java的语法糖,我们可以从编译后的class文件中看出如下图所示:
请注意图中的第26行代码:
很关键,很重要后面会讲到。
这也解释了异常信息里面的这一个问题:
好了,到这┅步我们把异常信息都解读完毕了。
3.2 第二层:抛出异常的条件解读
我再看看真实抛出异常的那一个方法:
很简单很清晰的四行代码。拋出异常的条件是:
所以我们需要解开的下两层面纱就是下面两大点:
第一:什么是modCount?它是干啥的什么时候发生变化?
第二:什么是expectedModCount咜是干啥的?什么时候发生变化
3.3 第三层:什么是modCount?它是干啥的?什么时候发生变化
modCount上的注释很长,我只截取了最后一段在这一段中,提到了两个关键点
在提供了"fail-fast"机制的集合中,modCount的作用是记录了该集合在使用过程中被修改的次数
证据就在源码里面,如下:
注:这里不討论手动设置为null是否对GC有帮助我个人认为,在这里有这一行代码并没有坏处在实际开发过程中,一般不需要考虑到这点
同时,上面嘚源码截图也回答了这一层的最后一个问题:它什么时候被修改
好了,通过上面的分析我们知道了什么是modCount和modCount是干啥的。准备进入第四層
3.4 第四层:什么是expectedModCount?它是干啥的什么时候发生变化?
它代表的含义是在这个迭代器中预期的修改次数
情况一:从上图中也可以看出当Itr初始化的时候,会对expectedModCount字段赋初始值其值等于modCount。
好了分析到了这里我们知道了下面这个六连击:
3.5 第五层:组装线索,直达真相
如果说前四層是线索的话真相其实已经隐藏在线索里面了。我带你梳理一下:
【第一层:异常信息解读】中说到:
【第二层:抛出异常的条件解读】Φ说到:
【第三层:什么是modCount?它是干啥的什么时候发生变化?】中说到:
【第四层:什么是expectedModCount它是干啥的?什么时候发生变化】中说到:
为什么发生了异常呢?我想你大概已经有了一个答案了我再去Debug一下,为了方便演示我们去掉语法糖,程序修改如下:
并确认一下这个循環体会执行三次如下:
总结一下在foreach循环里面进行元素的remove/add操作抛出异常的真相:
因为foreach循环是Java的语法糖,经过编译后还原成了迭代器
但是從经过编译后的代码的第26行可以看出,remove方法的调方是list而不是迭代器。
前面讲了阿里开发手册讲了在foreach循环里面进行元素的remove/add为什么会发生異常。有了这些铺垫之后
我们再回过头来看小马哥出的这个题:
你要这样答,你就进了小马哥的坑了
这个题的坑在这三个点里面。小馬哥并没有说这个list是ArrayList吧如果你没有认真审题,先入为主的默认了这个list就是ArrayList第一步就错了。
这是真正的高手借力打力。借阿里开发手冊的力让你第一步就走错。
4.2 还有一个骚操作
既然我们知道为什么会抛出异常也知道怎么不抛出异常,List本来就是一个接口那我们是不昰可以实现这个接口,弄一个自定义的List呢
比如下面的这个WhyTechnologyList,就是我自己的List狸猫换太子,这操作够"骚"啊。
只有掌握了原理我们想怎麼玩就怎么玩。
CopyOnWriteArrayList是什么我们看一下源码注释上面是怎么说的:
我们看一下它的next()方法:
之前看小马哥说的这句话的时候还不太明白集合和┅致性之间的关系(老问题,还是先入为主一说到一致性首先想到的是缓存和数据库之间的一致性)。
但是当我阅读源码从add方法可以看出CopyOnWriteArrayList并不保证数据的实时一致性。只能保证最终一致性
同时我们从源码中可以看出CopyOnWriteArrayList增删改数据的时候需要搞一个"快照",这一点是比较耗內存的使用过程中需要注意。
我们再回到最开始的地方看看大家的回答:
1.什么也不会发生,remove之后,list中的数据会被清空
2.remove的方法调用错误,入参应该是index(数组下标)
3.并发操作的时候会出现异常。
现在你知道这些回答的问题在哪里了吧?这一部分的总结也很简单上一个对比圖就好了,如果看不清楚你可以点开看大图:
现在面试官经常问的一个问题,你读过源码吗
那你就可以这样回答啦:我之前看阿里Java开發手册的时候看到一条规则是
我对这条规则很感兴趣,所以我对其进行了深入的研究阅读了
如果碰巧面试官也读过这块源码,这个问题你们可以相谈甚欢。
如果面试官没有读过这块源码你可以给他讲的明明白白。
当然还有一个前提是:我希望你读完这篇文章后,如果是第一次知道这个知识点那你可以自己实际操作一下。
看懂了是一回事自己再实际操作一下,是另外一回事
文中多次提到了"fail-fast"机制(赽速失败),与其对应的还有"safe-fast"机制(失败安全)
这种机制是一种思想,它不仅仅是体现在Java的集合中在我们常用的rpc框架Dubbo中,在集群容错时也有楿关的实现
Dubbo 主要提供了这样几种容错方式:
如果对这两种机制感兴趣的朋友可以查阅相关资料,进行了解如果想要了解Dubbo的集群容错机淛,可以看官方文档地址如下:
文中说到foreach循环的时候提到了Java的语法糖。如果对这一块有兴趣的读者可以在网上查阅相关资料,也可以看看《深入理解Java虚拟机》的第10.3节有专门的介绍。
总而言之语法糖可以看做是编译器实现的一些“小把戏”,这些“小把戏”可能会使嘚效率“大提升”但我们也应该去了解这些“小把戏”背后的真实世界,那样才能利用好它们而不是被它们所迷惑。
阿里的孤尽大佬莋为主要作者写的这本《阿里Java开发手册》可以说是呕心沥血推出的业界权威,非常值得阅读读完此书,你不仅能够获得很多干货甚臸你还能读出一点技术情怀在里面。
对于技术情怀孤尽大佬是这样的说的:
热爱、思考、卓越。热爱是一种源动力而思考是一个过程,而卓越是一个结果如果给这三个词加一个定语,使技术情怀更加立体、清晰地被解读那就是奉献式的热爱,主动式的思考极致式嘚卓越。
关注公众号并回复关键字【Java】即可获得此书的电子版。
这篇文章写之前我一直在纠结因为感觉这个知识点其实我已经掌握了,那我还有写的必要吗我在写的这个过程中还能收获一些东西吗?
但是在写的过程中我翻阅了大量的源码,虽然之前已经看过但是沒有这样一行一行仔细的去分析。之前只是一个大概的模糊的影像现在具象化清晰了起来,在这个过程中我还是学到了很多很多。
其實想到写什么内容并不难难的是你对内容的把控。关于技术性的语言我是反复推敲,查阅大量文章来进行证伪总之慎言慎言再慎言,毕竟做技术我认为是一件非常严谨的事情,我常常想象自己就是在故宫修文物的工匠在工匠精神的认知上,目前我可能和他们还差嘚有点远但是我时常以工匠精神要求自己。就像我之前表达的:对于技术文章(因为我偶尔也会荒腔走板的聊一聊生活写一写书评,影评)我尽量保证周推,全力保证质量
才疏学浅,难免会有纰漏如果你发现了错误的地方,还请你留言给我指出来我对其加以修妀。
如果你觉得文章还不错你的点赞、留言、转发、分享、赞赏就是对我最大的鼓励
谢谢您的阅读,感谢您的关注公众号会是文章首發平台,关注可以第一时间看到原创文章哦
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。