背景
在開始之前說說我的基本情況:c9本科雙非研究生20屆畢業,6月22號入職深圳今日頭條,在2020年12月搭上校招補錄的末班車上岸,崗位是android客戶端開發工程師。此文記錄一下我之前的面試經驗,順便分享一波複習資源,文末有資源鏈接自取。
我的秋招因爲被導師的項目耽誤了,所以10月份纔開始投遞簡歷,投遞字節跳動客戶端更是在掛了好幾家公司之後的11月底,算是撿了個校招補錄的便宜。因爲客戶端確實一直處於缺人狀態,所以相對其他崗位不容易飽和,競爭也沒那麼激烈,有想法的可以試一試。
言歸正傳,我的研究生專業是科學計算可視化,方向偏冷門。我的代碼能力尚可(c/c++),但數據庫/網絡基本沒有工程經驗(僅限於大三課程水平,遺忘過半),不會機器學習,不會java,沒有大廠實習經歷。
字節頭條一面(40min)
面試官只精通JAVA,而我只會C++,開始了愉快的交流,問題先後順序可能有誤(要不然上來兩個問題都不會面試官會懷疑審簡歷的眼瞎了)
- 自我介紹
- HTTP和HTTPS,get和post方法(答曰SSL加密,不瞭解更多,網絡相關的應用沒接觸,遂結束計網相關問題)
- 數據庫(表示不瞭解數據庫,上完課就沒用過記不清了,繼續問學生選課場景要怎麼建表,憋了一會兒答曰不會,遂結束數據庫相關問題)
- 進程&線程。創建子線程,若父線程終止,則子線程如何?(繼續運行直到線程自己結束)
- 進程間通信IPC(追問使用共享內存時如何進行同步)
- JAVA有GC機制,C++裏怎麼進行內存管理(手動new/delete,智能指針)
- 手寫Java雙重檢驗的單列模式
- Java的四種引用方式
- Java synchronized的類鎖和對象鎖,它們區別,哪些是對象鎖,哪些是類鎖
- 代碼題:歸併兩個有序鏈表(牛客、Leetcode原題)
字節頭條二面(40min):簡歷項目逐條撕
- 簡歷項目OpenGL渲染流程(按好幾年前的課程記憶大概背了幾點)
- 簡歷中的機器人項目,如何實現避障和路徑規劃
- TCP、UDP區別
- 操作系統線程和進程的同步機制和通信機制
- 什麼是緩存溢出
- osi和tcp/ip網絡模型,路由器和交換機位於哪一層
- Android中你常用哪些控件
- 說下Glide的使用
- RxJava的通信機制
- Android四大組件
- new和malloc
- 代碼:一開始出了個實現生產者消費者模型,表示不熟悉(模型只記得個大概,寫代碼是不可能完成任務)。換了個冒泡排序,我又表示太簡單。最後換成偶數長度的鏈表每兩個交換位置(1234 -> 2143)(有原題是鏈表每k個一組逆序,這題相當於k=2的情況)
- 隨便聊聊你沒有安卓開發經驗(潛臺詞:你研究生方向好偏啊JAVA都不會(╯‵□′)╯︵┻━┻)爲什麼選擇客戶端崗位?(答曰:本人不才,初中開始接觸編程參加NOIP,沒事兒就喜歡寫代碼。在計算機這個行業普遍很難做到專業和崗位對口,個人能力素質出色的話對很多崗位都是互通的blahblah……)
- 你通過哪些途徑學習新技術(答:主要由項目驅動,學習新技術主要通過閱讀官方文檔(這點很重要,不管你讀沒讀過,讀沒讀懂)和別人分享的技術博客,再加上自己的實踐)
字節頭條字節頭條三面(1h)
問的很細,幸好把方向引向了自己熟悉的領域:操作系統、數據結構&算法
(小插曲:第一天剛面10+分鐘面試官有緊急事情終止了,聽說是產品在美帝被告了要走法律流程orz,說改天繼續,當時我有點慌,幸好事後HR通知第二天接着面)
- 你在前面幾輪面試自我感覺如何(答了自己之前表現的優缺點,數據庫和網絡因爲科研學習沒有應用就不太熟悉,強調自己數據結構算法和操作系統掌握較好,事後回想這句纔是關鍵,避輕就重帶領面試方向)
- 圖像識別是怎麼做的
- 瞭解bitmap的解析嗎
- 設計一個自定義View,View中包含圖片和文字,並且只能繼承View
- 用過約束佈局嗎,它的特點和原理,比起相對佈局的優勢
- Glide相關
- https的加密過程,爲什麼要這麼做?
- 遊覽器輸入一個url後發生了哪些,dns協議原理
- get和post區別
- 封裝一個單鏈表,要求實現刪除,添加,反轉方法
- C有哪些庫函數
- static關鍵字(c中變量值保留,c++類成員可以不生成對象實例直接訪問(追問實現機制,答不上))
- 引用傳遞和值傳遞
- 說一說多態(靜態多態,動態多態,虛函數,虛函數表)
- C++類默認函數有幾個(構造、析構、拷貝、操作符=,C++11還有2個)
- TCP握手揮手
- 排序算法知道哪些(非比較排序(基數、桶)、比較排序(選擇冒泡插入、快排歸併堆排))
- 快排複雜度(期望O(NlogN))?最壞情況(O(N2))?什麼輸入最壞?(答曰有序最壞,分別追問順序和逆序,一開始腦癱說順序O(N)逆序O(N2)面試官奸笑:你再想想)
- 鏈表怎麼排序?說一下鏈表快排(口頭撕了蠻久的)
- 進程&線程?有哪些東西是線程共有的,獨立的
- 對鎖的認識(C++只有獨立鎖和共享鎖),談談樂觀鎖和悲觀鎖
- 死鎖?如何避免?
- 代碼題:
定義一個線程類
class Thread
{
int waiting;//等待資源的id
int count;//已佔有資源數量
int* holdings;//已佔有資源數組(數組內存有count個整數,代表佔有資源的id)
}
bool isThreadLocked(int n, Thread* thread)
{
//TODO
}
輸入一個長度爲N的Thread[]數組,判斷是否存在死鎖,返回true/false(哈希表+資源依賴鏈找環)
面試結果
11月25號投的簡歷,11月29號一二面,12月3日三面,12月9日offer-call,12月12日錄用函,這效率不可謂不快。
面試總結
面試官考察的基礎內容是有共同點的,無非是數據結構、計網、數據庫、操作系統、算法這幾門核心課的基礎知識(其實我一直覺得計網和數據庫不算核心課,畢竟很多方向和它倆不沾邊)。有不會的大方承認,千萬不要打腫臉充胖子。但是有一點很重要,字節跳動確實很看重coding,面試中的手撕代碼環節,紅黑樹雖不至於但至少快排二叉樹鏈表要熟練,然後再準備看一些leetcode中等題。
面試前準備
自我介紹
1、結合招聘崗位,只講重點
簡歷內容這麼多,實際的你,更有很多很多可以描述的東西。但時間有限,沒有面試官會聽你說個沒完。
根據你求職的崗位,說重點即可。
其實簡歷製作的原則,也是一樣。只是自我介紹時間更短,內容更精華。
2、有理有據,少說空話
如果你說“自己學習能力強”,這就是一句假大空的話。誰都可以說自己學習能力強。
你如果真的在這方面有突出,就要舉一個例子,比如是1個月從0到1考了什麼證書等。
3、有開頭有結尾,有邏輯
開頭問候,結尾總結。中間1、2、3條理清楚。
4、特別提醒
自我介紹中的內容,很可能是面試官後續發問的內容。所以,一是要引起重視,講最重要的,你最想讓面試官知道的內容。 而是做好準備,揚長避短,不要給自己挖坑。
比如前面你說自己學習能力強,但是沒有舉例子。
面試官很可能,順着你的話問你,怎麼證明你學習能力強呢? 結果你答不上來,或者是非常普通的成績,根本不能算是“學習能力強”。 那你就是給自己挖坑了。
其實自我介紹也是每個人各有不同,說起來也只能提供大致的思路。和你具體的求職崗位、經歷、個人風格有很大的關係。
掌握基礎知識
官方文檔就是教科書,源碼一定要抽時間多看,網上的分析和講解太多太亂,不要一味地跟着寫,這裏簡單列了幾個面試時喜歡反覆講的知識點。
- HashMap支持null Key和null Value;Hashtable不允許。因爲HashMap對null進行了特殊處理,將null的hashCode值定爲了0,所以將其存放在哈希表的第0個bucket。
- HashMap是非線程安全,HashMap實現線程安全方法爲Map map = Collections.synchronziedMap(new HashMap());Hashtable是線程安全
- HashMap默認長度是16,擴容是原先的2倍;Hashtable默認長度是11,擴容是原先的2n+1
- HashMap繼承AbstractMap;Hashtable繼承了Dictionary
- hashmap版本之間的區別,數據結構是怎樣的?
Java垃圾回收機制
需要理解JVM,內存劃分——方法區、內存堆、虛擬機棧(線程私有)、本地方法棧(線程私有)、程序計數器(線程私有), 理解回收算法——標記清除算法、可達性分析算法、標記-整理算法、複製算法、分代算法,優缺點都理解下。
需要了解下Activity棧和taskAffinity
- Standard:系統默認,啓動一個就多一個Activity實例
- SingleTop:棧頂複用,如果處於棧頂,則生命週期不走onCreate()和onStart(),會調用onNewIntent(),適合推送消息詳情頁,比如新聞推送詳情Activity;
- SingleTask:棧內複用,如果存在棧內,則在其上所有Activity全部出棧,使得其位於棧頂,生命週期和SingleTop一樣,app首頁基本是用這個
- SingleInstance:這個是SingleTask加強本,系統會爲要啓動的Activity單獨開一個棧,這個棧裏只有它,適用新開Activity和app能獨立開的,如系統鬧鐘,微信的視頻聊天界面不知道是不是,知道的同學告訴我下,在此謝過!
View的繪製流程
ViewRoot
->performTraversal()
->performMeasure()
->performLayout()
->perfromDraw()
->View/ViewGroup measure()
->View/ViewGroup onMeasure()
->View/ViewGroup layout()
->View/ViewGroup onLayout()
->View/ViewGroup draw()
->View/ViewGroup onDraw()
看下invalidate方法,有帶4個參數的,和不帶參數有什麼區別;requestLayout觸發measure和layout,如何實現局部重新測量,避免全局重新測量問題。
事件分發機制
->dispatchTouchEvent()
->onInterceptTouchEvent()
onTouchEvent()
requestDisallowInterceptTouchEvent(boolean)
還有onTouchEvent()、onTouchListener、onClickListener的先後順序
消息分發機制
這個考得非常常見。一定要看源碼,代碼不多。帶着幾個問題去看:
- 爲什麼一個線程只有一個Looper、只有一個MessageQueue?
- 如何獲取當前線程的Looper?是怎麼實現的?(理解ThreadLocal)
- 是不是任何線程都可以實例化Handler?有沒有什麼約束條件?
- Looper.loop是一個死循環,拿不到需要處理的Message就會阻塞,那在UI線程中爲什麼不會導致ANR?
- Handler.sendMessageDelayed()怎麼實現延遲的?結合Looper.loop()循環中,Message=messageQueue.next()和MessageQueue.enqueueMessage()分析。
其他性能優化
- 常量使用static final修飾
- 使用SparseArray代替HashMap
- 使用線程池管理線程
- ArrayList遍歷使用常規for循環,LinkedList使用foreach
- 不要過度使用枚舉,枚舉佔用內存空間比整型大
- 字符串的拼接優先考慮StringBuilder和StringBuffer
- 數據庫存儲是採用批量插入和事務
提升技能
Android學習是一條漫長的道路,我們要學習的東西不僅僅只有表面的 技術,還要深入底層,弄明白下面的 原理,只有這樣,我們才能夠提高自己的競爭力,在當今這個競爭激烈的世界裏立足。
如果你覺得自己學習效率低,缺乏正確的指導,可以參考下下面分享我多年工作以來收集整理的學習路線,給大家做個參考:
接下來是每個模塊我整理出來的文檔學習資料,幫助大家更細緻化的學習。
《Android彙總複習資料—Java》
《Android彙總複習資料—Android》
《Android彙總複習資料—Android擴展》
《Android彙總複習資料—Kotlin》
《Android彙總複習資料—Flutter》
《Android彙總複習資料—算法》
除了上面的學習路線,還可以額外的配合以下方式學習,效果翻倍~
①看視頻進行系統學習
前幾年的Crud經歷,讓我明白自己真的算是菜雞中的戰鬥機,也正因爲Crud,導致自己技術比較零散,也不夠深入不夠系統,所以重新進行學習是很有必要的。我差的是系統知識,差的結構框架和思路,所以通過視頻來學習,效果更好,也更全面。關於視頻學習,個人可以推薦去B站進行學習,B站上有很多學習視頻,唯一的缺點就是免費的容易過時。
另外,我自己也珍藏了好幾套視頻,有需要的我也可以分享給你。
②讀源碼,看實戰筆記,學習大神思路
“編程語言是程序員的表達的方式,而架構是程序員對世界的認知”。所以,程序員要想快速認知並學習架構,讀源碼是必不可少的。閱讀源碼,是解決問題 + 理解事物,更重要的:看到源碼背後的想法;程序員說:讀萬行源碼,行萬種實踐。
主要內含微信 MMKV 源碼、AsyncTask 源碼、Volley 源碼、Retrofit源碼、OkHttp 源碼等等。
③面試前夕,刷題衝刺
面試的前一週時間內,就可以開始刷題衝刺了。請記住,刷題的時候,技術的優先,算法的看些基本的,比如排序等即可,而智力題,除非是校招,否則一般不怎麼會問。
關於面試刷題,我個人也準備了一套系統的面試題,幫助你舉一反三:
④2020大廠面試高頻知識點
- 圖片
- 網絡和安全機制
- 數據庫
- 插件化、模塊化、組件化、熱修復、增量更新、Gradle
- 架構設計和設計模式
- 性能優化
- Android Framework
- Android優秀三方庫源碼