我的2017是忙碌的一年,從年初備戰實習春招,年三十都在死磕JDK原始碼,三月份經歷了阿里五次面試,四月順利收到實習offer。然後五月懷著忐忑的心情開始了螞蟻金服的實習。八月,又經歷了兩輪面試,總算拿到轉正offer。到此為止,我總算可以盡情地享受最後的校園時光了。 希望我的經歷與感悟能幫助到大家。
我的讀研經歷
阿里是我讀研階段的一個重要目標,剛上研一的時候我便立下Flag,計劃了讀研三年要做的事情、要學的東西。翻翻我的部落格,居然還能找到當時寫的讀研計劃(想想時間過的真的好快呀)。阿里在我心中一直是技術者的朝聖地,聚集了一群技術狂熱分子,為了提升一點點的效能可以廢寢忘食。在立下這個flag後,我便把我要去阿里的想法告訴了身邊的所有人。我不想給自己留有後路,既然牛逼吹出去了,那就得落實到行動上。
我當時的計劃是這樣的,研一玩命做專案,畢竟寫程式碼是一項孰能生巧的技術,多寫程式碼自然能加深對技術的理解。事實也確實證明了這一點。我大四畢業的那個暑假,第一次接觸《深入理解JVM虛擬機器》,當時看完之後是一臉懵逼的,所有的漢字都認識,但連成一條句子後咋就不明白呢?然後懷著這種一臉懵逼的狀態,強行把這本書看完了,但由於理解的不夠深刻,很快就忘記了。然後經過一年瘋狂做專案,當我再抱起這本書時,我對這本書的感覺有了180度的轉變,通俗易懂啊。我懷疑自己當時為什麼這麼傻。而在這一年之內,我一共做了四個專案。所以說,寫程式碼能潛移默化地提升你對技術的理解程度。
記得我們學校考研結果公佈是在三月底,得知我錄取了,短暫的高興了一下,第二天便去了導師實驗室,參與到專案中去。因為我心理很清楚,我的目標是阿里。 剛去實驗室的時候感覺自己完全是一隻小白,師兄們開會討論的東西我竟然一個字都聽不懂,剛開始分到的工作也很難順利的完成。但我是一個天生不服的人,我越是不懂,我越是要征服。(PS:追女生也一樣,當時看上了一個高冷型女神。越是高冷,我越要拿下……省略一萬字……最後成功了)。我漸漸跟上了師兄們的步伐,從第二個專案開始,我一直是專案負責人了。 我給自己定的方向是Java,而實驗室的專案五花八門,Qt、C++、影像圖形……,但我心裡清楚,這些專案可以拓寬我的視野,可以鍛鍊我的學習能力、思維方式,但要深入理解的技術還是Java。所以我利用專案空窗期,看了很多Java方面的書籍,文末我列了一份清單供大家參考。
研一做了一年專案之後,感覺自己解決問題的能力、快速上手新技術的能力有所提升,但做專案一味求快、一味趕時間,我對很多技術的理解僅停留表面。所以更多時候我感覺自己是在搬磚,很難寫出高質量的程式碼。當時我決定,研二的上半學期一定要好好穩固基礎,深入理解技術背後的原理,放慢做專案的節奏,不一味地盲目求快。
然而研二因為種種原因,我去了一家創業公司實習。既然我無法選擇,那我就擁抱變化。既來之則安之,我希望自己所花的時間都有所收穫。所以我全身心投入到工作中去。公司安排我做前端,雖然這並不是我想幹的事情,但當前別無選擇,既然做那就得做好。我花了一個月的時間怒刷前端知識,學習Angular、React,瞭解它們的設計思想,學習JS背後的原理,也看到了前端目前的發展狀況。前端的技術迭代速度很快,但技術背後的原理都是類似的,所以抓住技術背後的本質才是最重要的。 這段實習一直持續到了今年一月,我心理清楚,二月底三月初阿里的實習招聘就要開始,所以我擠出中午休息時間、晚上下班後的時間、週末的時間,複習我之前積累的東西。
三月三號,人生的第一次面試,在看到杭州的電話時,那一刻的心情既忐忑又興奮。在此之前,我並不清楚自己的水平在所有應屆生中處於一個怎樣的層次,在電話接通之前我已經做好了充分的心理準備,想象了各種被面試官吊打的畫面。第一次面試持續了54分鐘,面試官似乎破有耐心,整個面試過程相談甚歡。那一次的面試給了我巨大的信心,因為我清楚,我離我的目標更近了一步。 在接下來的一個月中,我陸陸續續接到了五次面試電話,每一次面試都是一次學習的機會,能發現自己的不足,在與面試官交流的過程中也能瞭解到最新的技術、最佳的實現方法。
四月十四,記得那天剛替導師給本科生上完演算法課,晚飯過後便收到的阿里的offer。當時的喜悅之情溢於言表,這麼久的努力沒有白費。但我心裡也清楚,阿里的實習轉正率向來很低,要想通過實習留下來也不是一件容易的事。所以在收到阿里offer之後的那晚,我重新規劃了接下來的學習計劃,將我的短期目標更新成:拿下阿里轉正offer。
5.20,一個美好的日子,我懷著憧憬、忐忑、興奮的心情走進了支付寶大樓,開始了我三個月的實習生涯。這三個月的實習讓我學到了很多,我看到了每天的進步,也看到了自己的不足。這100天經歷了太多的事情,有太多的體會,有空我再單獨寫一篇實習期間的感悟與大家分享。
9.1晚上11點,我的狀態從『面試中』變成了『待跟進offer』,我會心一笑,我達成了人生第一階段的目標。那一刻我沒有太多的激動,在經過了2017年8個月的持久作戰之後,這個offer早已在我的意料之中。
第二天是週六,這個週末我給自己放了兩天的假。雖然在杭州已經呆了102天,雖然支付寶大樓就在西湖邊,但每天兩點一線的工作,我並沒有去過西湖。那一晚我的基友得知我收到offer後便立即買票,坐了一夜的火車來杭州為我慶祝。也託他的福,在這個週末我第一次遊覽了這座美麗的城市。
最後的校園時光,我給自己定了一個新的目標,這個目標也許充滿了挑戰、充滿了艱辛與困難,但我想如果能達成,我的人生將會有很大的改變。在人生的路上,我還在奮鬥。希望與各位共勉。
一些建議
在面試阿里的過程中,部落格幫了我很大的忙。並不是說有部落格在面試中會加分,而是寫部落格的過程能加深你對知識的理解,而且回顧起來也特別高效(畢竟是自己寫的東西)。
我從研一開始便養成了寫部落格的習慣,現在先過頭來,這兩年我一共寫了185篇文章,有22W的訪問量,也很榮幸稱為專家博主。我的部落格現在已經成為我一筆最寶貴的財富,記錄了我技術的整個體系結構,也記錄了學習技術的心路歷程。
可能很多同學都有寫部落格的經歷,但能長期堅持的少之又少。我想告訴大家,任何事情都貴在堅持。只要堅持21天就能養成習慣。有的時候對這件事缺乏興趣了很難再持續下去,但想想自己的目標,咬咬牙堅持下去,養成習慣你就贏了。
我的部落格一般都是看完一本書後的總結,我會把一本書中最核心的東西,按照我的理解把它們記錄下來。每一本書我都會看三遍,第一遍是快速瀏覽,瞭解整本書的體系結構、作者的行文思路,知道書中重要的、不重要的內容,也就是要建立起全域性觀。第二遍我會精讀,把那些我認為重要的內容挑選出來著重閱讀、反覆理解、吃透。第三遍閱讀,往往會冒出新的理解,我時常有這種『書讀百遍,其義自見』的感覺。三遍讀完後,我便按照自己的理解,把核心內容寫成部落格。由於是自己的寫的東西,所以在複習的時候只要花上三五分鐘通讀一遍,所有的知識點又被喚醒。
Java面試考點梳理
本文是根據我的面試經驗,為大家整理Java程式猿面試所需的知識體系。
第一部分:計算機基礎
網際網路大廠都相當重視程式設計師的基本功,也就是計算機基礎知識。一個程式設計師能走多遠、爬多高,很大程度上取決於基本功是否紮實。對於應屆生而言,大都比較缺乏實戰專案經驗,雖然會有一定的專案經驗,但這些課程設計、實驗室專案的質量與公司實際的專案有著巨大的差距。因此,基礎知識便成為面試考量的一大重點,而且基礎紮實的程式設計師可塑性比較高,做什麼都能比較容易快速上手。
計算機基礎包含如下幾門課程,相信計算機專業的同學肯定都已經學過。但網際網路公司面試的考點可能和你們期末考試的考點有一些不同,我都做了整理。
1. 計算機網路
大學課程中的計算機網路一般都按照OSI七層參考模型介紹,然而由於網際網路公司的特性,他們更加關注日常開發所涉及到的傳輸層和應用層,所以需要重點掌握傳輸層和應用層中所涉及到的所有知識點。
【考點】
- 傳輸層的作用
- 傳輸層複用和分用的含義
- 傳輸層和網路層的區別
- UDP協議的特點
- UDP協議的報文結構
- TCP協議的特點
- TCP協議的報文結構
- TCP三次握手過程
- TCP四次揮手過程
- TCP可靠傳輸是如何實現的
- 停止等待協議
- 滑動視窗協議
- TCP的流量控制
- TCP擁塞控制
- HTTP協議
- HTTP工作流程
- HTTP請求格式
- HTTP 1.1中的8種請求方式
- HTTP響應格式
- HTTP中重要的請求頭和響應頭欄位
- HTTP常用狀態碼及其含義
- HTTPS協議
- HTTPS協議與HTTP協議的區別
- HTTPS協議的工作流程
【資料整理】
- 計算機網路傳輸層知識點全覆蓋-大閒人柴毛毛的部落格
- HTTP詳解(1)-工作原理
- HTTP詳解(2)-請求、響應、快取
- HTTP詳解(3)-http1.0 和http1.1 區別
- 圖解 HTTPS 通訊過程
2. 資料結構
熟練掌握資料結構是程式設計師最最最基本的素養,在實際開發中選擇合適的資料結構將極大影響程式的效率。面試官一般並不會直接問資料結構的問題,而是通過出一些包含資料結構的演算法題來考察你對資料結構的理解程度以及在實際專案中是否能夠靈活應用。你可以通過刷演算法題來提升這部分能力,推薦《劍指offer》和《程式設計師面試金典》(注意是金典!)。很多公司的演算法題庫都選自這兩本書。
當然,刷這兩本書的目的並不是讓你死記硬背題目,題目千變萬化,面試官可以隨意改變。刷演算法題最重要的是培養解決問題的思路和解決實際問題的能力。在刷題的過程中要多多總結,再次強調,切忌死記硬背!
3. 演算法
和資料結構一樣,演算法一般也通過具體的演算法題來考察,你也可以通過刷《劍指offer》和《程式設計師面試金典》中的演算法題來提高這方面的技能。但在刷這些演算法題之前,你需要掌握幾類基礎的演算法,並理解他們解決問題的思路(這才是最為關鍵的)。這些演算法我已經在下面整理。
4. 作業系統
【考點】
- 作業系統的四個特性。
- 作業系統的主要功能。
- 程式的有哪幾種狀態,狀態轉換圖,及導致轉換的事件。
- 程式與執行緒的區別。
- 程式通訊的幾種方式。
- 程式同步的幾種方式
- 使用者態和核心態的區別。
- 死鎖的概念,導致死鎖的原因。
- 導致死鎖的四個必要條件。
- 處理死鎖的四個方式。
- 預防死鎖的方法、避免死鎖的方法。
- 程式排程演算法。
- 記憶體連續分配方式採用的幾種演算法及各自優劣。
- 基本分頁儲存管理方式。
- 基本分段儲存管理方式。
- 分段分頁方式的比較各自優缺點。
- 幾種頁面置換演算法,會算所需換頁數
- 虛擬記憶體的定義及實現方式。
【資料整理】
5. 資料庫
【考點】
- 什麼是索引?
- 索引的分類
- 索引的優缺點分析
- 何時需要使用索引?何時無需使用索引?
- 什麼是事務?
- 事務的四大特性
- 資料庫三大正規化
- 資料庫有哪些表連線?
【資料整理】
第二部分:Java
作為一名合格的Java程式設計師,僅瞭解如何使用Java是遠遠不夠的。你能夠熟練使用Java只能說明你已經成為一名合格的碼農,能夠利用Java實現某些功能。而公司作為盈利機構,需要用最少的資源實現效益最大化,這就需要程式設計師具備高質量程式碼的能力,而能否寫出高質量程式碼取決於你對技術背後原理的理解程度。只有在理解Java背後的原理,你才能根據Java的特性,寫出更加高效的程式碼。這在實際業務中是非常有價值的事情。網際網路大廠服務海量使用者,更加註重系統的效能,也更加註重程式設計師對原理的理解。
關於Java的基礎知識和如何使用,這裡我就不提了,隨便一本Java書籍都有詳細的介紹。這裡我整理了Java原理性的知識點,這些知識點將會成為你面試的加分項。
1. Java虛擬機器
【考點】
- Java虛擬機器記憶體模型特點和作用
- 程式計數器
- Java虛擬機器棧
- 本地方法區
- 堆
- 方法區
- 物件建立過程
- 物件訪問過程
- 物件的記憶體結構
- 垃圾收集演算法
- 如何判定哪些物件需要回收?
- 物件記憶體分配策略
- 分配擔保機制
- 垃圾收集器的比較
- Class檔案結構
- 類載入的時機
- 類載入過程
- 雙親委派模型
【知識點資源整理】
- 深入理解JVM(一)——JVM記憶體模型
- 深入理解JVM(二)——揭開HotSpot物件建立的奧祕
- 深入理解JVM(三)——垃圾收集策略詳解
- 深入理解JVM(四)——物件記憶體的分配策略
- 深入理解JVM(五)——HotSpot垃圾收集器詳解
- 深入理解JVM(六)——JVM效能調優實戰
- 深入理解JVM(七)——Class檔案結構
- 深入理解JVM(八)——類載入的時機
- 深入理解JVM(九)——類載入的過程
- 深入理解JVM(十)——類載入器
2. Java併發程式設計
【考點】
- 什麼是死鎖?如何避免死鎖?
- 什麼是重排序?
- volatile有哪些特性?
- 什麼是記憶體可見性?
- volatile為什麼能夠保證記憶體可見性?
- 中斷機制
- 執行緒通訊有哪些方式?
- 執行緒池的作用?
- ThreadPoolExecutor如何使用?
- 如何設定執行緒池的大小?
- 如何保證執行緒安全?
- JDK 1.6哪些對鎖做了哪些優化?
【知識點資源整理】
- Java併發程式設計的藝術(一)——併發程式設計需要注意的問題
- Java併發程式設計的藝術(二)——重排序
- Java併發程式設計的藝術(三)——volatile
- Java併發程式設計的藝術(四)——執行緒的狀態
- Java併發程式設計的藝術(五)——中斷
- Java併發程式設計的藝術(六)——執行緒間的通訊
- Java併發程式設計的藝術(七)——Executors
- Java併發程式設計的藝術(八)——閉鎖、同步屏障、訊號量詳解
- Java併發程式設計的藝術(九)——批量獲取多條執行緒的執行結果
- Java併發程式設計的藝術(十)——執行緒池(1)
- Java併發程式設計的藝術(十一)——執行緒池(2)
- Java併發程式設計的藝術(十二)——執行緒安全
- Java併發程式設計的藝術(十三)——鎖優化
- Java併發容器大合集
3. Java 容器考點及資料整理
- Java 集合系列01之 總體框架
- Java 集合系列02之 Collection架構
- Java 集合系列03之 ArrayList詳細介紹(原始碼解析)和使用示例
- Java 集合系列04之 fail-fast總結(通過ArrayList來說明fail-fast的原理、解決辦法)
- Java 集合系列05之 LinkedList詳細介紹(原始碼解析)和使用示例
- Java 集合系列06之 Vector詳細介紹(原始碼解析)和使用示例
- Java 集合系列07之 Stack詳細介紹(原始碼解析)和使用示例
- Java 集合系列08之 List總結(LinkedList, ArrayList等使用場景和效能分析)
- Java 集合系列09之 Map架構
- Java 集合系列10之 HashMap詳細介紹(原始碼解析)和使用示例
- Java 集合系列11之 Hashtable詳細介紹(原始碼解析)和使用示例
- Java 集合系列12之 TreeMap詳細介紹(原始碼解析)和使用示例
- Java 集合系列13之 WeakHashMap詳細介紹(原始碼解析)和使用示例
- Java 集合系列14之 Map總結(HashMap, Hashtable, TreeMap, WeakHashMap等使用場景)
- Java 集合系列15之 Set架構
- Java 集合系列16之 HashSet詳細介紹(原始碼解析)和使用示例
- Java 集合系列17之 TreeSet詳細介紹(原始碼解析)和使用示例
- Java 集合系列18之 Iterator和Enumeration比較
4. Java IO 考點及資料整理
- java io系列02之 ByteArrayInputStream的簡介,原始碼分析和示例(包括InputStream)
- java io系列03之 ByteArrayOutputStream的簡介,原始碼分析和示例(包括OutputStream)
- java io系列04之 管道(PipedOutputStream和PipedInputStream)的簡介,原始碼分析和示例
- java io系列05之 ObjectInputStream 和 ObjectOutputStream
- java io系列06之 序列化總結(Serializable 和 Externalizable)
- java io系列07之 FileInputStream和FileOutputStream
- java io系列08之 File總結
- java io系列09之 FileDescriptor總結
- java io系列10之 FilterInputStream
- java io系列11之 FilterOutputStream
- java io系列12之 BufferedInputStream(緩衝輸入流)的認知、原始碼和示例
- java io系列13之 BufferedOutputStream(緩衝輸出流)的認知、原始碼和示例
- java io系列14之 DataInputStream(資料輸入流)的認知、原始碼和示例
- java io系列15之 DataOutputStream(資料輸出流)的認知、原始碼和示例
- java io系列16之 PrintStream(列印輸出流)詳解
- java io系列17之 System.out.println("hello world")原理
- java io系列18之 CharArrayReader(字元陣列輸入流)
- java io系列19之 CharArrayWriter(字元陣列輸出流)
- java io系列20之 PipedReader和PipedWriter
- java io系列21之 InputStreamReader和OutputStreamWriter
- java io系列22之 FileReader和FileWriter
- java io系列23之 BufferedReader(字元緩衝輸入流)
- java io系列24之 BufferedWriter(字元緩衝輸出流)
- java io系列25之 PrintWriter (字元列印輸出流)
- java io系列26之 RandomAccessFile
- 深入分析 Java I/O 的工作機制