面试会问源码吗?一般怎么问?如何阅读源码?(完结)




面试会问源码吗?一般怎么问?如何阅读源码?(完结)
一、为什么要阅读源码?
1)面试会问
这个是毫无疑问的,对于 Java 程序员来说,面试中不会一直问源码,但至少会问一些。
比如说:看你简历写做了线程池调优,能讲下线程池的原理以及做了哪些优化吗?
那你就要和面试官聊了一下线程池源码里的一些细节。
比如说:线程安全的类有哪些,平时有使用么,用来解决什么问题?
那像 CopyOnWriteArrayList、ConcurrentHashMap 就要重点聊聊了,之前如果没有研
究这两个类的源码的话,是很容易翻车的。
我之前在星球里分享过一篇:《如何在 3 天内学会 Java?》里面的 14)源码阅读
• String
• Integer
• ArrayList
• LinkedList
• HashMap
• TreeMap
• LinkedHashMap
• ConcurrentHashMap
• CopyOnWriteArrayList
这几个类是阅读 JDK 源码中的重中之重。
2)学习优秀的代码实践
你有没有想过这样一个问题:怎样才能提高自己的编程能力?
土办法:造轮子。
怎么造?肯定要站在巨人的肩上,先去阅读别人的源码,看看别人是怎么造的,这又是一
个拆轮子的过程。
印象中,我感觉自己的编程能力突飞猛进的时刻好像有两次。
第一次是在外企的时候,研究日方提供的框架源码,然后当组件不满足需求的时候亲手造
出来了那么两三个,当然是在基于原有的组件基础上,但就这么两三个重组后的组件,让
我在团队中的地位瞬间就抬升了很高一个档次,因为别人都在用轮子,并且还用不好,我
却可以造轮子了。
后面之所以被领导破格提升为小组长也是因为这茬事,紧跟着后面的那次涨薪幅度也比较
大。
第二次是我开始系统化分享技术博客的时候,因为要给大家讲清楚,那必须得多拆轮子,
不论是读书、读博客、读源码,还是看视频,首先得做到自己确实把要讲的事情给研究透
彻了,然后才能按照自己喜欢的方式行文,达到通俗易懂、风趣幽默的效果。
鲁迅曾提到过一个主义,大家应该都能立马想得到——拿来主义。
闷头一直写自己的代码,只会坐井观天,不知道外面的世界有多美好,不知道别人的代码
写得多优雅!
通常来说,GitHub 上星标比较高的开源项目,代码写得都非常的优雅,质量高、扩展性
强,所以如果你不知道该如何提升自己的代码能力时,就去拿来主义,先模仿,再理解,
然后主动“造轮子”,久而久之,你的代码能力就会越来越强。
不知道看哪些开源项目的话,可以在星球里面查看开源项目板块,我会一直不停地分享。
3)工作需要
也很好理解,不管是工作中还是学习中,我们都很少会从 0-1 的搭建一个项目,比如说
Java 程序员,在搭建一个项目的时候,肯定会用到 Spring Boot,那 Spring Boot 的源码要
不要学习?肯定是有需要的,比如说为什么 Spring Boot 项目不需要额外安装 Tomcat,那
肯定就要研究一下@SpringBootApplication 注解。
再比如说,项目开发中用到了某个开源组件,它有 bug,或者不能满足实际的项目需要,
那要不要学习源码?肯定也是要的。
解铃还须系铃人嘛。
还有,我们在学习 Java 的时候,像 String 类、Integer 类、HashMap 类、ArrayList 类等
等,都是要深入 JDK 的源码内部,去学习的,不然像字符串常量池啊,Integer 缓存啊,
HashMap 的哈希原理啊,ArrayList 的自动扩容啊,根本不知道为什么。
另外,工作当中,我们不可避免地会接手一个其他人的项目,那自然是要阅读别人写过的
代码的,不然很难上手。
读代码和写代码是两个不太一样的技能,原因在于“写代码的是在表达自己,读代码的是
在理解别人”。
二、面试一般怎么问源码?
就简单举一些例子吧:
1、你看过哪些源码?
2、那你能讲讲 HashMap 的实现原理吗?
3、HashMap 什么时候会进行 rehash?
4、结合源码说说 HashMap 在高并发场景中为什么会出现死循环?
5、JDK1.8 中对 HashMap 做了哪些性能优化?
6、HashMap 和 HashTable 有何不同?
7、HashMap 和 ConcurrentHashMap 的区别?
8、 ConcurrentHashMap 和 LinkedHashMap 有什么区别?
9、为什么 ConcurrentHashMap 中的链表转红黑树的阀值是 8?
10、还看过其他的源码吗?Spring 的源码有了解吗?
11、SpringBoot 的源码呢?知道 starter 是怎么实现的吗?
三、如何阅读源码?
1)必须要有一定的积累
阅读源码之前,最好有一定的积累,如果你连 Java 基础都还没有打好,为了看源码去看
源码肯定是不行的,只会一脸懵逼,建议至少把 Java 基础部分学习完后,再尝试看源
码。
Java 基础都包含哪些部分?
可以去二哥的网站《Java 程序员进阶之路》上查看以下这部分内容:
• Java 概述
• Java 基础语法
• 面向对象
• 字符串 String
• 数组
• 集合框架(容器)
• 异常处理
• 常用工具类
• Java8 新特性
• Java 重要知识点
其实在学习这部分内容时,就会涉及到一部分源码,比如说字符串 String 类是 JDK 中必
读的一部分源码,还有集合框架中的 ArrayList、LinkedList、HashMap 这些,都是非常经
验的源码阅读对象。
如果你在学习源码的过程中遇到困难,不要硬着头皮上,很容易被劝退,尤其是新手阶
段。但如果你的反馈是津津有味,那么可以很肯定地说,你是一颗学习 Java 的好种子。
2)由简单到复杂
切忌一上来就去啃 ConcurrentHashMap、CopyOnWriteArrayList 这些涉及到并发编程的
源码,也切忌去啃 Spring IoC 和 AOP 这类较为复杂的源码。可以先去啃 String 类这种比
较简单的,给自己建立起信心,然后再去由浅入深。
1647042988478-3450ea16-5359-42a8-adfa-bd29e19f9e47.png
慢慢的我们的编程思维跟上了,再去啃一些硬核的源码就会得心应手。
如果实在是啃不动,可以先搜一些好的源码分析的文章,跟着别人一步步来学习,直到自
己看简单的源码也不吃力了,再去尝试有挑战性的源码来阅读。
Java 源码应该是这个世界上最好的 Java 范例了,规整,结构清晰,前后的逻辑缜密,关
键是文档也非常的详细,一上来不要先盯着代码看,可以先通过文档大致了解一下这个
类,这个方法是干嘛的,再逐行地去看代码,如果遇到比较惊艳的,令自己拍案而起的代
码,记得做好笔记,下次自己在写类似的代码时,作为参考。
我现在不管是学习新东西还是看源码,都会做笔记,有巧妙的逻辑、设计模式、好的方法
会进行记录。我一直认为好记性不如烂笔头,再经常拿出来看,项目中进行运用,这才是
看源码最终应该有的效果,最终受益的肯定是我们自己。
3)反复看、明确目的
第一次看源码不要要求自己太多,先看个大概,过段时间再来看就会发现清晰不少,一定
要多看,所谓书读百遍其义自见,看多了,你就会有新的发现。
尽管阅读源码非常重要,但并不见得所有的项目都需要从头到尾看的清清楚楚,所以要有
明确的目的,自己是要了解整体的架构,还是了解某个算法的实现。
总之,不建议毫无目的的开始阅读源码,无头苍蝇式的乱砍只会消耗自己的热情和时间。
4)保持好奇心
看源码的时候,一定要保持好奇心,为什么作者要这样实现,换另外一个方法行不行?
举个简单的例子,比如说为什么 JDK 源码中,无限循环大多使用 for(;;)而不是
while(true),你可能就会刨根问底出来很多新奇的东西。
for (;;) 在 Java 中的来源,可以追溯到 C 语言,这些人不一定是自己以前写 C 习惯了这样
写,可能是间接受以前写 C 的老师、前辈的影响而习惯这样写的。
在 Java 里我是倾向于写 while (true)的,不过我也不介意别人在他们自己的项目里写 for
(;;)。
以 Java 8 的实现来看,javac 对下面这两串代码的编译结果基本上是完全一样的。
1647044157803-536415c9-6afc-48f1-b5f2-7c0532a01a01.png
5)善用工具
阅读源码的第一个工具,就是你手里的 Intellij IDEA,把代码编译通过,运行起来,加
log,试着修改一些数据和代码,看看有什么变化。
有的项目比较复杂,依赖的组件比较多,搭建起来一个调试环境并不容易,所以不见得能
顺利跑起来。如果能自己编译跑起来,后面的情景分析、代码调试才能展开。
通过调试去看源码是学习源码的最佳方式,切记直勾勾地盯着源码去看,会很容易雾里看
花,抓不住重点。
1647042518400-9d3eaa00-2ed6-40f2-a1ab-d0604fe51a75.png
第二个重要的工具就是 debugger,而 debugger 最重要的功能就是获取调用堆栈,在你不
知道怎么用的方法里加一个断点,通过调用堆栈可以让你对整个方法的原理有一个更清晰
的认知。
1647042842495-9953f543-b660-4553-88f0-2941c7cbc9ec.png
四、总结
和任何其他你可以习得的技能一样,阅读源码这种能力也是需要长时间积累,反复训练
的,不可能在短时间内就有突飞猛进的效果。要注意平时的积累,遇到自己感兴趣的,不
明所以的,就点个断点,调试一番,不积小流无以成江海。
我向你保证,如果能够保持耐心读完一个项目的源码,你一定会收获巨大。