意外收获
我在写文章的过程中,还有意外收获。就是一个读者提出的这个问题:为什么迭代器里面的hasNext()里面要用!=来判断index和size之间的关系,而不是用<符号呢。
当时我并没有留意到这个问题,我觉得就是都可以,无关紧要。但是写的时候我突然想明白了,这可不是无关紧要的事,这地方必须是 【!=】。
我给你看个表格:
在上面的程序中我把判断条件改为了【cursor<size】,当执行到第三次循环,cursor=2,size=1时。用cursor<size返回的是false,则不会继续循环,所以不会触发fail-fast机制。如果用cursor!=size返回的是true,会继续执行循环,所以会触发检查modCount的操作,触发fail-fast机制。
正如我截图中说的:这里用【!=】判断,是符合它的语境的。用迭代器循环的时候,循环结束的条件就是循环到最后一个元素就停止循环。但是这一条件的前提是在我循环的过程中,集合大小是固定的。如果集合大小发生了变化,那就会触发fail-fast机制。
智子封锁:Debug下的问题
说到这个问题,我真的觉得我被智子封锁了,我开始理解那些科学家为什么要自杀了。如果你读过《三体》,你知道我在说什么。
不论是用我们自定义的WhyArrayList还是JDK的ArrayList结果都是一样的,为了结果的直观,我用WhyArrayList给你演示一下:
第一步是没有问题的:
所以程序在Debug模式下的输出变成了这样:
我的Idea版本是:IntelliJ IDEA 2019.2.4 (Ultimate Edition)
我的JDK版本信息如下:
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_212-b03)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.212-b03, mixed mode)
如果你也碰到过,你知道是怎么情况,请你告诉我究竟是怎么回事,是不是计划的一部分。
扩展阅读
本文前传
答应我,如果你不知道这个知识点,想完全掌握的话,一定要去读一读本文的前传《这道Java基础题真的有坑!我求求你,认真思考后再回答。》。两篇文章合计一起食用,味道更佳。
本文代码
本文的源码我已经上传到git上了,git地址如下:
git clone git@github.com:thisiswanghy/WhyArrayList.git
fail-fast机制和fail-safe机制
文中多次提到了"fail-fast"机制(快速失败),与其对应的还有"fail-safe"机制(失败安全)。
这种机制是一种思想,它不仅仅是体现在Java的集合中。在我们常用的rpc框架Dubbo中,在集群容错时也有相关的实现。
Dubbo 主要提供了这样几种容错方式:
Failover Cluster - 失败自动切换
Failfast Cluster - 快速失败
Failsafe Cluster - 失败安全
Failback Cluster - 失败自动恢复
Forking Cluster - 并行调用多个服务提供者
如果对这两种机制感兴趣的朋友可以查阅相关资料,进行了解。如果想要了解Dubbo的集群容错机制,可以看官方文档,地址如下:
http://dubbo.apache.org/zh-cn/docs/source_code_guide/cluster.html
Java语法糖
文中说到foreach循环的时候提到了Java的语法糖。如果对这一块有兴趣的读者,可以在网上查阅相关资料,也可以看看《深入理解Java虚拟机》的第10.3节,有专门的介绍。
书中说到:
总而言之,语法糖可以看做是编译器实现的一些“小把戏”,这些“小把戏”可能会使得效率“大提升”,但我们也应该去了解这些“小把戏”背后的真实世界,那样才能利用好它们,而不是被它们所迷惑。
阿里Java开发手册
阿里Java开发手册中也有对该问题的描述,强制要求:
不要在foreach循环里面进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
阿里的孤尽大佬作为主要作者写的这本《阿里Java开发手册》,可以说是呕心沥血推出的业界权威,非常值得阅读。读完此书,你不仅能够获得很多干货,甚至你还能读出一点技术情怀在里面。
对于技术情怀,孤尽大佬是这样的说的:
热爱、思考、卓越。热爱是一种源动力,而思考是一个过程,而卓越是一个结果。如果给这三个词加一个定语,使技术情怀更加立体、清晰地被解读,那就是奉献式的热爱,主动式的思考,极致式的卓越。
关注公众号并回复关键字【Java】。即可获得此书的电子版。
最后说一句
如果你之前对于这个知识点掌握的不牢固,读完这篇文章之后你会知道有这么一个知识点,但是仅仅是知道,不是一个十分具化的印象。只有你实际的操作一下之后,才能算是掌握了,源码会刻在你的潜意识里面。久久不会忘记。这部分现在对我来说,我输出了共计1万3千多字的文章,在我的脑海中固若金汤。
所以我个人建议,最好再去实际操作一下吧。git地址我前面给你了。
再推销一下我公众号:对于写文章,其实想到写什么内容并不难,难的是你对内容的把控。关于技术性的语言,我是反复推敲,查阅大量文章来进行证伪,总之慎言慎言再慎言,毕竟做技术,我认为是一件非常严谨的事情,我常常想象自己就是在故宫修文物的工匠,在工匠精神的认知上,目前我可能和他们还差的有点远,但是我时常以工匠精神要求自己。就像我之前表达的:对于技术文章(因为我偶尔也会荒腔走板的聊一聊生活,写一写书评,影评),我尽量保证周推,全力保证质量。坚持输出原创。
才疏学浅,难免会有纰漏,如果你发现了错误的地方,还请你留言给我指出来,我对其加以修改。
以上。
谢谢您的阅读,感谢您的关注。