閱讀源碼是每個(gè)優(yōu)秀開(kāi)發(fā)工程師的必經(jīng)之路,那么這篇文章就來(lái)講解下為什么要閱讀源碼以及如何閱讀源碼。
首先來(lái)說(shuō)下為什么要讀源碼,有學(xué)習(xí)源碼的必要嗎?
為什么要閱讀源碼?
關(guān)于為什么閱讀和學(xué)習(xí)源碼,我個(gè)人認(rèn)為可能有以下幾點(diǎn):
(一)吊打面試官,應(yīng)對(duì)面試
為了找到更好的工作,應(yīng)對(duì)面試,因?yàn)樵诿嬖囍锌隙〞?huì)問(wèn)到源碼級(jí)別的問(wèn)題,比如:為什么 HashMap
是線程不安全的?
如果你沒(méi)有閱讀過(guò)源碼,面試官可能會(huì)對(duì)回答的結(jié)果不滿意,進(jìn)而導(dǎo)致面試結(jié)果不太理想,但如果你對(duì)源碼有所研究,并能夠很好地問(wèn)答面試官的問(wèn)題,這可能就是你的加分點(diǎn),可以形成自己獨(dú)特的競(jìng)爭(zhēng)力,吊打面試官,升職加薪不是夢(mèng)。
(二)解決問(wèn)題(bug)
在開(kāi)發(fā)過(guò)程中,我們或多或少會(huì)遇到 bug
,比如:在 foreach
循環(huán)里進(jìn)行元素的 remove/add
操作,為啥有可能會(huì)報(bào) ConcurrentModificationException
異常?
我們可以先在 Google、Stack Overflow
以及對(duì)應(yīng)項(xiàng)目的 Issues
里看有沒(méi)有類(lèi)似問(wèn)題以及解決辦法,如果沒(méi)有的話,我們只能通過(guò)閱讀源碼的方式去解決了。如果我們對(duì)相關(guān)源碼有所涉獵,就可以快速定位到問(wèn)題所在。
(三)提升編程能力
讀一本好書(shū),就是和許多高尚的人談話。-歌德
和閱讀一本好書(shū)一樣,閱讀源碼就是和編程大牛面對(duì)面交流的機(jī)會(huì),在許多優(yōu)秀的開(kāi)源項(xiàng)目中,它們的編碼規(guī)范和架構(gòu)設(shè)計(jì)都是很棒的,另外在設(shè)計(jì)上也使用了大量的設(shè)計(jì)模式,通過(guò)閱讀和學(xué)習(xí)源碼,能夠快速提升我們的編碼水平,以及對(duì)設(shè)計(jì)模式有更深的理解。
同時(shí),在我們閱讀完一個(gè)源碼后,可以觸類(lèi)旁通,能夠快速地對(duì)其他框架的源碼進(jìn)行閱讀和學(xué)習(xí),減少時(shí)間成本。
除了上述提到的原因之外,可能還有許多,在這里就不一一贅述了,那么在確定了要閱讀源碼之后,就讓我們看下如何閱讀源碼吧!
如何閱讀源碼?
如何閱讀源碼取決于你為什么要讀源碼,比如:
-
如果為了應(yīng)對(duì)面試,那就可以圍繞常考的 基礎(chǔ)類(lèi)、集合類(lèi)、隊(duì)列、線程、鎖等內(nèi)容進(jìn)行閱讀和學(xué)習(xí); -
如果是為了解決 bug
,那么就可以只圍繞出現(xiàn)問(wèn)題的相關(guān)類(lèi)進(jìn)行閱讀分析,隨著解決bug
的增多,我相信閱讀的源碼也會(huì)越多,從而更容易去閱讀和學(xué)習(xí)源碼;
下面大概說(shuō)下閱讀源碼的幾點(diǎn)建議:
在閱讀之前,可以先從開(kāi)源項(xiàng)目的官網(wǎng)上看它的架構(gòu)設(shè)計(jì)和功能文檔,了解這個(gè)項(xiàng)目的整體架構(gòu)、模塊組成以及各個(gè)模塊之間的聯(lián)系。
如果沒(méi)有對(duì)應(yīng)的項(xiàng)目文檔,可以根據(jù)代碼的模塊進(jìn)行梳理,以形成對(duì)項(xiàng)目的初步了解,或者查看已有的源碼解析文章或者書(shū)籍,在閱讀源碼之前,了解項(xiàng)目的架構(gòu)和思路會(huì)使閱讀源碼事半功倍。
在了解一個(gè)類(lèi)的時(shí)候,可以使用 ctrl+F12
來(lái)查看類(lèi)中的成員變量和方法。
可以通過(guò) IDEA 的 Diagrams
功能去了解一個(gè)類(lèi)的繼承關(guān)系。
多打斷點(diǎn)調(diào)試,斷點(diǎn)追蹤源碼是很好的閱讀源碼的方式,可以先通過(guò) debug
了解下調(diào)用邏輯,都和哪些類(lèi)有關(guān)聯(lián),有大致了解后再通過(guò) debug
了解整體代碼的功能實(shí)現(xiàn),各個(gè)類(lèi)都起到了什么作用,有沒(méi)有涉及到設(shè)計(jì)模式等。
另外,優(yōu)秀的開(kāi)源項(xiàng)目中肯定會(huì)有許多地方應(yīng)用到了設(shè)計(jì)模式,建議在閱讀源碼之前,需要對(duì)常用的設(shè)計(jì)模式有大致的了解,不然閱讀源碼的效率會(huì)大大降低。
如果遇到讀不懂某部分源碼的時(shí)候,可以先跳過(guò),之后再回來(lái)看,如果屬于搞不懂這部分就茶不思飯不想的人,可以在網(wǎng)上找是否有該部分源碼的解析或者文檔,也可以自己通過(guò)源碼注釋和測(cè)試用例去閱讀學(xué)習(xí)。
一般優(yōu)秀的開(kāi)源項(xiàng)目都會(huì)有單元測(cè)試,可以通過(guò)對(duì)應(yīng)類(lèi)的單元測(cè)試去了解方法的含義和用法,加深對(duì)源碼邏輯的理解。
在閱讀源碼的時(shí)候,可以在代碼上加上注釋和總結(jié),同時(shí)還可以畫(huà)出時(shí)序圖和類(lèi)圖,這樣對(duì)閱讀源碼有很大的幫助,可以很清楚地知道類(lèi)之間的調(diào)用關(guān)系和依賴(lài)關(guān)系,也方便以后回顧,重新閱讀。
在這里推薦大家一個(gè) IDEA 插件 SequenceDiagram
,可以根據(jù)源碼生成調(diào)用時(shí)序圖,便于閱讀源碼。
剛開(kāi)始閱讀源碼,不建議直接看框架源碼,可以先從 jdk 源碼看起:
jdk 源碼也是非常龐大的,可以分模塊來(lái)閱讀,下面是建議的閱讀順序:
-
java.lang
包下的基本包裝類(lèi)(Integer、Long、Double、Float
等),還有字符串相關(guān)類(lèi)(String、StringBuffer、StringBuilder
等)、常用類(lèi)(Object、Exception、Thread、ThreadLocal
等)。 -
java.lang.ref
包下的引用類(lèi)(WeakReference、SoftReference
等) -
java.lang.annotation
包下的注解的相關(guān)類(lèi) -
java.lang.reflect
包下的反射的相關(guān)類(lèi) -
java.util
包下為一些工具類(lèi),主要由各種容器和集合類(lèi)(Map、Set、List
等) -
java.util.concurrent
為并發(fā)包,主要是原子類(lèi)、鎖以及并發(fā)工具類(lèi) -
java.io
和java.nio
可以結(jié)合著看 -
java.time
主要包含時(shí)間相關(guān)的類(lèi),可以學(xué)習(xí)下 Java 8 新增的幾個(gè) -
java.net
包下為網(wǎng)絡(luò)通信相關(guān)的類(lèi),可以閱讀下Socket
和HTTPClient
相關(guān)代碼
其他包下的代碼也可以做下了解,JDK源碼閱讀筆記:https://github.com/wupeixuan/JDKSourceCode1.8
再有了一定的源碼閱讀經(jīng)驗(yàn)后,可以再去學(xué)習(xí) Spring、Spring Boot、Dubbo、Spring Cloud
等框架的源碼。
總結(jié)
本文主要介紹了為什么讀源碼以及如何讀源碼,供大家參考,每個(gè)人都有適合自己的閱讀源碼的方式,希望可以在學(xué)習(xí)中去摸索出一套屬于自己的方式。
閱讀源碼不是一蹴而就的,這是持久戰(zhàn),只要你能夠堅(jiān)持下來(lái),肯定受益匪淺。閱讀源碼的過(guò)程比較枯燥,可以在社群里一起討論學(xué)習(xí),這樣可能效率更高些。
寫(xiě)得不好的或者大家有什么更好的建議,也歡迎留言討論。
特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒(méi)關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:
長(zhǎng)按訂閱更多精彩▼
如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!