面試前
今年8月份的時候,向以下公司投遞了簡歷:百度、騰訊、阿里巴巴、網易、京東,其中京東和阿里巴巴把我筆試給掛了,其余公司的筆試過了。阿里巴巴把我筆試掛了我感覺很坦然,因為筆試題做得實在不好,而京東把我的筆試掛了我就覺得很奇怪,當時大部分題目都做得還可以,只有一道算法題沒做出來,后來就沒過。不過都是往事了,有空把筆試經歷總結一下,下面開始把面試經歷好好回憶一下,因為已經過了兩個星期,我盡量回憶一下吧。
百度面試
百度一面
百度一面在成都金牛區的一家酒店里,百度在候面區組織面試的人很少,只有兩三個人的樣子。一面大概持續了三天,技術崗和非技術崗在不同的地點面試。面試大概從早上九點開始,中午12點暫停休息,下午2點繼續開始,持續到下午6點,一場面試一般會持續一個小時左右。所以一天大概有6到7批人面試,每一批大概有30人左右,技術崗的一面持續約3天。所以可以估算出成都地區進入一面的人數:
3*7*30=630人。
一面的面試官是個很平易近人的程序員,我進了房間把簡歷遞給他后他并沒有細看。(一面和二面的面試官都沒怎么細看簡歷,也許是之前已經看過了電子簡歷?)
我坐下來后他也并沒有要我做自我介紹,而是主動問我什么時候開始做Android的,Java又是什么時候開始學的?我回答說2015年9月份開始自學Android的,也是那個時候開始學Java的。到現在差不多一年了。
然后他問:你Java學得如何?還算熟悉嗎?我回答:我Java學得不算熟悉,但是也為了面試多多少少看了一些面試題。(沒錯,就是這么耿直,然后面試官就笑了,我也笑了。)
氣氛就這么輕松下來了,他問:那我們開始吧,先來個簡單的,說一下String、StringBuffer和StringBuilder的用法和區別吧。我回答:String的內部實現為final char[],所以每次對現有的字符串修改的話都會新實例化一個String,所以頻繁的字符串修改和拼接要用StringBuffer,在單線程環境下用StringBuilder,性能更好,因為可以避免加鎖帶來的性能損耗。
他問:JDK里面的容器用過吧,把你所熟知的集合列舉出來并說一下他們的用處。(不得不說這個問題很考基礎,還好我都研究一遍了。。。= =)我回答:ArrayList,LinkedList,Vector,Set,TreeSet,HashMap,TreeMap,LinkedHashMap,HashTable,然后我把他們內部的實現和常用操作的時間復雜度給說了一遍,甚至還把OpenJDK、OracleJDK和Apache Harmony Project JDK內部的實現的差異給說了一下。這個問題的回答有很多細節答錯了,比如我把Collection接口和Set接口給弄混了,但是答得很多還到處拓展地講了一下,面試官好像還比較滿意。
他問:你在項目中肯定用到多線程了吧,你們多線程是如何交互的呢?我一下子暈了,不知道”多線程交互“指的是什么,他也有點無奈,就進一步說是主線程和子線程之間的通信,我一下子就明白了,就隨口說了一個Handler。
他繼續追問:使用Handler要注意什么呢?我答:1、在非主線程中初始化之前要調用Looper.prepare()。2、防止內存泄漏,用WeakReference保存活動或碎片的引用。
他問:學校里學過算法吧,手寫一個快速排序吧。我就巴拉巴拉寫了一個給他看。
他問:用兩個棧實現一個隊列。當時我知道這是一個老套路的題了,但是我以前偏偏沒認真思考過這個問題,當時馬上給出的解時間效率不高,他有些不滿意,就一步步引導我,好在我也不覺得緊張,想了想就把結果想出來了。
他問:你在項目里怎么保證應用切入后臺,音樂服務不被殺死呢?(我的項目是一個音樂軟件的項目)我知道這又是Service保活的老套路,答了兩點:1、onStartCommand()返回START_STICKY。2、服務切換成前臺服務。 只答了這兩點他就沒難為我了。
他問:多個Fragment如何共享一個ActionBar呢?如果在MainActivity已經有了一個ActionBar的情況下子Fragment又實例化一個ActionBar會發生什么呢?這個問題我很懵,就瞎扯了會有多個ActionBar重疊。
他問:多個Fragment共享一個ActionBar的情況下,如果想要在不同的Fragment下使用不同的Menu怎么辦呢? 然后我就被問傻了,直接說我沒接觸過這個問題,他就開始告訴我怎么實現,巴拉巴拉說了幾句后好像突然意識到我只是個本科生,就笑了笑,切換到下個問題。
他問:你在項目中怎樣實現的圖片加載呢?我答說用的Picasso。然后他問這個框架看過源碼嗎,我就回答看過,然后寫出了幾個主要的類,然后把緩存策略跟他講了講(LRU,七分之一可用堆空間,50MB磁盤控件),和緩存的實現也講了講(LinkedHashMap,HttpClient的緩存),他看上去好像也不是很了解這個庫,就沒有多追問。
他問:你在項目中怎樣實現內存的優化呢?我回答:主要優化圖片的內存占用,首先對圖片重新裁剪,根據控件占用的實際像素數對圖片進行resize,然后根據服務器上的該類型圖片是否有透明通道決定要不要把alpha通道給砍掉。他點了點頭,就切換到下個問題。
他問:如果讓你實現一個圖片加載框架,你打算怎么做?我回答:還是用LinkedHashMap做內存緩存,用圖片的URL做主鍵,做兩級緩存。我知道這個問題我答得還不夠,但是面試官挺寬容的,沒有多刁難我。
他問:你用過sqlite嗎?他跟mysql有什么顯著的區別嗎?這個問題把我難住了,就隨口扯了扯,他跟我解釋了幾句sqlite的表存儲在哪,又交流了一下sqlite的性能后,也沒有多刁難我。
他問:描述一下Android里面的控件的事件分發過程。我回答:一個事件傳遞給ViewGroup時,ViewGroup先決定要不要攔截這個事件,如果要攔截,就在onInterceptTouchEvent(MotionEvent e)這個回調用返回true,然后交給這個控件來消費。如果不攔截的話,ViewGroup內部保存了它的孩子View的列表或者數組,然后遍歷這個數組逐一詢問他們是否要攔截。 當時表述地不是很清楚,面試官確認了幾遍就結束了這個問題。
他問:寫過JNI嗎?我回答:沒在項目中寫過,平時寫過幾個demo。然后扯了扯這個JNI寫起來很蛋疼,類型不匹配就容易崩,在IDE還不容易看到。他好像有同感的樣子,笑了笑,一面的問題就全部結束了。
最后他問還有什么要問他的,我又很搞笑地說:沒什么要問的。他就主動扯了扯一些技術方向。我很感謝這位面試官,他最后很關切地問我是不是要回重慶去,我說我要留在這里等面試結果,他就建議我先回重慶去,因為面試結果還要等兩天才能出來。
百度二面
兩天后我接到百度的二面的通知,我又趕到了成都市。面試地點沒有變,二面的人比起一面要少多了,沒有看到霸面的同學。二面大概持續了2天左右,每一批的人都要少了很多,我估計進入二面大概有200~300人左右。
二面的面試官沒有一面的面試官那么和藹可親,他總是面無表情,然后不停地切換到下一個問題。讓我手寫代碼地時候他只是面部表情地盯著他的MacBook。一開始讓我做了一個自我介紹,然后馬上就開始了面試。
他問:平時用過觀察者模式嗎?說一下你對觀察者模式的理解吧。我就說多個界面同時觀察一個數據變化的情況,說了一下觀察者模式的實現,就是被觀察者保存觀察者的列表,有數據變化就遍歷這個列表去通知觀察者。他好像有點不滿意。
他問:Builder模式呢?我就說了一下用Builder模式來實現一個配置參數類的構造,他聽得有點懵就把我打住,讓我把Builder模式寫一遍。我就巴拉巴拉寫了一個給他看,他點了點頭。
他接下來又讓我寫了一個快速排序,我有些無奈,一面二面考到同樣的題,于是又原樣寫了一個給他看。
他問:寫一個函數,給定一個單鏈表和頭指針和鏈表的某一個結點,在O(1)的時間內刪除這個結點。我思考了一下,覺得O(1)內刪除這個結點是不可能的,因為我沒法在O(1)內獲取到要刪除的這個結點的前向結點。我就問他:能否邏輯上刪除這個結點,而不是實際刪除。他點了點頭說可以。我又問他:有沒有可能要刪除尾結點?他說有可能,我馬上就不干了,當即跟他說這不可能,他想了想,笑了笑,就說那就不刪除尾結點。
struct Node{
Node *next;
int val;
Node () {next=NULL;}
};
void removeNode(Node*head, Node*target){
if (!head || !target)
return;
if (target->next){
Node *temp=target->next;
target->val=target->next->val;
target->next=temp->next;
delete(temp);
}
}
他叫我手寫一個回調函數的實現。我就隨手寫了一個給他看,他點了點頭。
他問:HashMap的內部結構?這也是老套路了,我就畫了個圖給他看。他就沒說什么,繼續下一題。
他問:解釋一下紅黑樹吧。我當時有些記不得了,就說:1、平衡二叉樹。2、插入、刪除、查詢復雜度O(nlgn)。(這里答錯了,當時頭有點暈)3、根節點和葉結點是黑節點,從根節點到葉結點經過的黑節點數目相同。(這個也不知道有沒有答錯,面試官當時也是面無表情。)
他問我對深拷貝和淺拷貝的理解。我就很抖機靈地拿前面那個鏈表那一題舉例,說只拷貝鏈表地頭節點就是淺拷貝,拷貝整個鏈表就是深拷貝。他笑了笑,沒好氣地叫我說好一點。我就說:一個對象實際在堆空間中存在,如果只拷貝一個對象的引用,使得多個引用指向同一個堆空間內的對象,這就是淺拷貝。如果拷貝了實際的對象,使得堆空間內有兩個對象,就是深拷貝。
他繼續追問:怎樣實現一個類的深拷貝呢? 這個問題我有點沒底氣,就說了兩個方法。1、定義一個拷貝構造函數,對傳入的對象的每個成員進行拷貝。2、實現Cloneable接口。也不知道答得對不對,面試官也沒有太多反應。
他讓我在紙上寫出Fragment的生命周期。 我就巴拉巴拉寫了整個過程給他看。
他問:Android內部的WebView用過吧,Android怎樣跟js交互呢? 我就直接說我沒有接觸過HTML5和原生的混合開發。
他問:應用上線后,如果應用出錯了,異常信息如何收集呢? 講真我也沒接觸過這個問題,但是還是能猜一猜的。我就說,catch到的異常可以getCause()和getMessage(),把這些異常信息寫入文件或數據庫中,定期打包上傳到服務器。他也沒說什么。
他問:你這個應用的項目的架構是如何設計的? 我就回答:用的Retrofit+RxAndroid,圖片加載用的Picasso。整體是一個MVP架構。他又問這個MVP架構的內部的大體類結構如何,我就寫了幾個代表性的接口和類,給他演示不同層次間如何通信。
他問:項目如何實現用戶個人信息的安全性?我回答說用https,他又追問我對Https的理解。我就說會多幾次握手,有一定性能消耗,加密原理上應該是利用了大整數的因式難分解,在傳輸層和應用層加了一個加密層。
他問:如何實現微信上的一個自定義控件。我剛準備說自定義控件的過程就被他打住了,這個問題有點怪怪的,他主要考察的是我有沒有真正地寫過一個自定義控件,問了我api如何設計等等。把我給考住了。
然后二面就差不多結束了,他問我有啥要問的。我就隨口扯了扯,問他對這個行業的發展趨勢看法。他就說Android市場雖然差不多飽和了,高級人才還是缺得很等等。整個二面對手寫代碼的能力考察得比較頻繁,面試官提的問題也更靈活和貼近實戰。
百度面試總結
百度的面試總體上來比較正常,考察地范圍比較均衡和穩定。所有面試官應該都共用了一個”考察題庫“,我甚至可以瞥到他們在紙上列出地題目列表。題目會覆蓋到Java基礎、Android基礎、設計模式、Android項目的實際問題的解決方案、算法和數據結構,經常會碰到經典套路的題目,如果實現刷過這些面試題會很輕松。
百度面試的題目雖然大體上比較穩定,但是不同的面試官還是有自己的考察特點,有的面試官比較和善,會去積極引導你回答問題,有的面試官會喜歡問你項目中的實際問題,而不是紙上談兵。
最后結果:二面掛了,我雖然覺得二面表現尚可,可是還是掛了,可能我還需要提高吧。