本人近況
年底裁人了,一年半沒準(zhǔn)備面試了,之前換也是內(nèi)推的,在這個(gè)寒冬的冬天還經(jīng)歷此遭,偏偏還趕上裁員
心態(tài)早已爆炸,大的環(huán)境不好,各位且干且珍惜....
記錄下最近的面試經(jīng)歷,整理下讓自己不斷進(jìn)步!
題外話
我不知道一個(gè)人人性究竟可以壞到什么程度,但是我最近親身經(jīng)歷的確實(shí)是這樣,我一個(gè)安心想做技術(shù)的人跟你TMD HR部門的八竿子打不著,又何苦為難我呢? 之前有個(gè)公司的薪酬績效主管,邵X,只因?yàn)槲以诖髸享斪擦怂粋€(gè)問題,一味著揪著我的把柄不放,甚至特么的為了少給我一個(gè)季度的績效不允許提前轉(zhuǎn)正,真的是壞透了,可能這就是職場,這就是江湖充滿爾虞我詐,真的人真是身不由己的,本想與世無爭安心踏實(shí)做技術(shù),但是某些人卻看不得你的安寧。。。還是那句話,出來混的遲早要還的,望好自為之
右劃
這公司是在拉勾上投的,CEO號稱曾于字節(jié)跳動,任視頻負(fù)責(zé)人,創(chuàng)建了頭條視頻APP。公司待遇15薪非常不錯(cuò),坐落于望京Soho對面的望京融科寫字樓
- 面試過程覺得自己挺失敗的沒有充分準(zhǔn)備算法再加上由于一年半沒有再面試過了,有點(diǎn)手生,好多應(yīng)該答上來的問題都沒有答好,面試官確實(shí)是大牛,沒會的問題也稍微講解了下,不過深度確實(shí)蠻深的
- 印象比較深的幾個(gè)問題:Lru算法,Binder機(jī)制,EventBus實(shí)現(xiàn)原理和為什么不能跨進(jìn)程,Handler如何在handleMessage方法攔截之前發(fā)出的message,手寫二分法查找(沒準(zhǔn)備直接跪了),后來讓我手寫冒泡,我覺得前面已經(jīng)沒戲了(大致說了下雙重循環(huán)然后賦值也沒手寫),跨進(jìn)程幾種方式,AIDL,handler機(jī)制,ThreadLocal實(shí)現(xiàn)原理(回答的很模糊,附上正確答案:每個(gè)Thread的對象都有一個(gè)ThreadLocalMap,當(dāng)創(chuàng)建一個(gè)ThreadLocal的時(shí)候,就會將該ThreadLocal對象添加到該Map中,其中鍵就是ThreadLocal,值可以是任意類型。
在該類中,最重要的方法就是兩個(gè):set()和get()方法。當(dāng)調(diào)用ThreadLocal的get()方法的時(shí)候,會先找到當(dāng)前線程的ThreadLocalMap,然后再找到對應(yīng)的值。set()方法也是一樣。)系統(tǒng)是如何監(jiān)聽ANR的(他說是androidframework層有一個(gè)單獨(dú)的進(jìn)程),后來問到如何定位和排查我不小心說了blockCanary,他有追問了一下源碼和原理我回答的也不是很好(應(yīng)用發(fā)生卡頓,一定是在dispatchMessage中執(zhí)行了耗時(shí)操作。我們通過給主線程的Looper設(shè)置一個(gè)Printer,打點(diǎn)統(tǒng)計(jì)dispatchMessage方法執(zhí)行的時(shí)間,如果超出閥值,表示發(fā)生卡頓,則dump出各種信息,提供開發(fā)者分析性能瓶頸。)
最后知道今天一定掛了,不過還是很有收獲的知道自己哪里不足...
PS:明天去五道口面試斗魚,希望能好好把握
斗魚
拉勾投的斗魚,據(jù)說最近在瘋狂裁人?只經(jīng)歷了兩輪面試,一共面了兩個(gè)多小時(shí),沒到HR,估計(jì)歇菜了
- 斗魚有份筆試題,還是蠻簡單的隨便寫寫就ok,一面問的蠻詳細(xì)的,問的大致是看簡歷寫的東西問的,中規(guī)中矩,記憶比較深刻的是問了handlerThread原理,MVP模式(因?yàn)槎肤~目前的架構(gòu)都是mvp),彈幕的實(shí)現(xiàn)原理和重疊問題(這個(gè)沒怎么做過,回答的不是太好,而且之前也是直接用的B站開源的那個(gè)庫),Kotlin協(xié)程(這個(gè)沒用過,kt的掌握程度還只是入門階段),Retrofit+Okhttp+Rxjava在華為的好多手機(jī)會OOM是由線程數(shù)溢出引起如何解決?堆內(nèi)存,棧內(nèi)存理解,棧如何轉(zhuǎn)換成堆?內(nèi)存泄漏是發(fā)生在堆內(nèi)存還是棧內(nèi)存?為什么? BlockCanary原理?(第二次被問了?。?!看來真要看看源碼了)如何實(shí)現(xiàn)打印指定阻塞線程的方法名?LinkedHashMap與HashMap區(qū)別。。。
String a=“A” 與 String a = new String(“A”); 區(qū)別,分別存儲在哪個(gè)區(qū)域(這題有誤導(dǎo)嫌疑,第一個(gè)應(yīng)該是常量區(qū),堆棧都不是,第二個(gè)是堆)MutiDex 第一次ANR以及解決方式(答案參考:http://www.lxweimin.com/p/5a2e33a61ba2)
我覺得大部分的問題回答的還是不錯(cuò)的,一面問了下薪資然后開始二面 - 二面印象最深的是根據(jù)面向?qū)ο笤O(shè)計(jì)一個(gè)電梯系統(tǒng),問題的關(guān)鍵點(diǎn)在于所有的屬性都跟電梯有關(guān),跟人無關(guān),樓層數(shù)是固定的常量...我當(dāng)時(shí)設(shè)計(jì)跑偏了,總聯(lián)想到人然后去設(shè)計(jì)。。
結(jié)束以后沒有HR面,估計(jì)歇菜了...再接再厲吧...
Zenjoy
這家公司是獵頭推薦的,坐落于銀河SohoA座,辦公環(huán)境蠻不錯(cuò)的,產(chǎn)品方向是做海外項(xiàng)目的,不過前后歷經(jīng)將近三個(gè)小時(shí)的面試著實(shí)很令人崩潰,我喝了將近三瓶小瓶怡寶礦泉水才撐到了最后。。。
一面&二面
一面,二面問的太多了根本記不住,只記得幾個(gè)印象深刻的問題,
- hashcode()和equals()的作用、區(qū)別、聯(lián)系?
因?yàn)閔ashCode()并不是完全可靠,有時(shí)候不同的對象他們生成的hashcode也會一樣(生成hash值得公式可能存在的問題),所以hashCode()只能說是大部分時(shí)候可靠,并不是絕對可靠,所以我們可以得出:
1.equal()相等的兩個(gè)對象他們的hashCode()肯定相等,也就是用equal()對比是絕對可靠的。
2.hashCode()相等的兩個(gè)對象他們的equal()不一定相等,也就是hashCode()不是絕對可靠的。) - Handler、Looper、MessageQueue、Thread關(guān)系?
一個(gè)線程可以有多個(gè)Handler實(shí)例,一個(gè)線程對應(yīng)一個(gè)Looper,一個(gè)Looper也只對應(yīng)一個(gè)MessageQueue,一個(gè)MessageQueue對應(yīng)多個(gè)Message和Runnable。所以就形成了一對多的對應(yīng)關(guān)系,一方:線程、Looper、MessageQueue;多方:Handler、Message。同時(shí)可以看出另一個(gè)一對一關(guān)系:一個(gè)Message實(shí)例對應(yīng)一個(gè)Handler實(shí)例。 - Service 和 Activity如何交互, 如何在后臺下載任務(wù), 并在Activity顯示進(jìn)度?
- https握手過程,如何實(shí)現(xiàn)數(shù)據(jù)加密?客戶端如何保證安全實(shí)現(xiàn)雙重證書校驗(yàn)?請你設(shè)計(jì)一個(gè)登錄功能,需要注意哪些安全問題?
- Hashmap實(shí)現(xiàn)原理和如何解決散列碰撞(必問),Hashmap底層為什么是線程不安全的?
- HandlerThread原理以及對比單個(gè)New Thread的好處,優(yōu)點(diǎn)以及試用場景?需要注意的是HandlerThread 是單個(gè)線程的不太適合執(zhí)行網(wǎng)絡(luò)的IO操作,要注意。。
- EventBus實(shí)現(xiàn)原理
- SurfaceView, TextureView區(qū)別?
從性能和安全性角度出發(fā),使用播放器優(yōu)先選SurfaceView。
1.在android 7.0上系統(tǒng)surfaceview的性能比TextureView更有優(yōu)勢,支持對象的內(nèi)容位置和包含的應(yīng)用內(nèi)容同步更新,平移、縮放不會產(chǎn)生黑邊。 在7.0以下系統(tǒng)如果使用場景有動畫效果,可以選擇性使用TextureView
2.SurfaceView優(yōu)點(diǎn)及缺點(diǎn)優(yōu)點(diǎn):可以在一個(gè)獨(dú)立的線程中進(jìn)行繪制,不會影響主線程,使用雙緩沖機(jī)制,播放視頻時(shí)畫面更流暢
缺點(diǎn):Surface不在View hierachy中,它的顯示也不受View的屬性控制,所以不能進(jìn)行平移,縮放等變換,也不能放在其它ViewGroup中。SurfaceView 不能嵌套使用
3.TextureView優(yōu)點(diǎn)及缺點(diǎn)
優(yōu)點(diǎn):支持移動、旋轉(zhuǎn)、縮放等動畫,支持截圖
缺點(diǎn):必須在硬件加速的窗口中使用,占用內(nèi)存比SurfaceView高,在5.0以前在主線程渲染,5.0以后有單獨(dú)的渲染線程。 - handler postDelay這個(gè)延遲是怎么實(shí)現(xiàn)的?
- Appliction啟動過程(App啟動過程)?
- 如何測量應(yīng)用啟動時(shí)間?
1.可以通過代碼打樁,計(jì)算啟動時(shí)間
2.命令
adb shell am start -W [packageName]/[packageName.launchActivity]
三面
根據(jù)之前獵頭的情報(bào),三面是沒有技術(shù)相關(guān)的問題的,但是我這個(gè)不一樣,三面是總監(jiān)面,首先先手寫一個(gè)算法,不難,大致意思是:給你一個(gè)無序的數(shù)組,又給了一個(gè)目標(biāo)值,如果這個(gè)數(shù)組其中有兩個(gè)數(shù)相加等于這個(gè)目標(biāo)值,請你輸出對應(yīng)兩個(gè)數(shù)的下標(biāo)?
思路也蠻簡單的,直接Arrays.sort先排序 按升序來,然后雙重循環(huán)就可以了。。。寫完總監(jiān)會問下單層for循環(huán)時(shí)間復(fù)雜度---
for(int i=1;i <=n;i++) //O(N);
for(int j=1;j <=i;j++) //O(N^2);
然后是
- 設(shè)計(jì)模式
- Restful接口規(guī)范 我倆爭論了好半天
- 觀察者模式的原理
大概能記得的就是這些,總監(jiān)可能比較注重基礎(chǔ)吧,自認(rèn)為總體發(fā)揮一般可能一面和三面有一些瑕疵,主要二面有一些問題反問面試官也沒有給我相應(yīng)的解釋比如那個(gè)handler postDelay怎么delay的。。。前前后后面了將近三個(gè)小時(shí),最后HR進(jìn)來讓我回去等消息,我知道估計(jì)涼涼了。。。
萊熙科技
這家公司我依稀記得去年年初考慮新機(jī)會的時(shí)候,那時(shí)候還在職,偷偷去面過,真心覺得面試官總是問一些我意想不到的問題,原本是要拒了的,可是Boss直聘上HR小姐姐一再要求要我再來一次,我就安排了今天的第三面(第一面已經(jīng)拿到offer但是工資與預(yù)期差距較大,而且沒有太深的技術(shù)面再加上公司較小,與我預(yù)期的差距也很大就不寫了)依稀記得大概一年零八個(gè)月前吧,那時(shí)候他們還沒做海外項(xiàng)目,沒想到現(xiàn)在的產(chǎn)品居然是我上家公司的同類競品項(xiàng)目,他們做的叫LivU,Live Chat,在線視頻聊天~于是我決定去試試水。。。
一面
面試官還是1年零八個(gè)月之前的小哥,問題問的果然沒有辜負(fù)我對他的期望,因?yàn)楫a(chǎn)品做的都是一個(gè)路子還有用的框架也是Agora的,答起來輕車熟路,但是有好多讓我耳目一新的問題
- 使用GreenDao如何實(shí)現(xiàn)創(chuàng)建表、關(guān)聯(lián)表(一對一,一對多,多對多)?
- Java調(diào)用kotlin 如何不用companion object{}包裹?
我解答他之前一直糾結(jié)的:在Java中調(diào)用kotlin中靜態(tài)的成員
如果一個(gè)類中所有的成員都是靜態(tài)成員,將class改為object就不用每個(gè)方法都用companion object{}包裹了。但是小哥說據(jù)說是最新kotlin加個(gè)注解可以不需要這個(gè)包裹? - 斷點(diǎn)續(xù)傳實(shí)現(xiàn)
- 代理模式和裝飾器模式區(qū)別?
- java io 裝飾器模式。。當(dāng)時(shí)問我用過的哪個(gè)包是裝飾器模式,我沒答上來!
- App啟動速度優(yōu)化?
- Android 5.0-8.0新特性
- Dalvik與ART區(qū)別?
- 進(jìn)程保活?(偽命題)沒有真正意義的進(jìn)程?;?,都是白明單才OK
- Retrofit CreateApi實(shí)現(xiàn)原理
二面
二面主要是總監(jiān)面試,穿插了一些技術(shù),不過總是暗示我來了需要加班啥的要我考慮清楚(我當(dāng)然想你錢到位,啥都不是事)不過既然這么說了,因?yàn)槲覇柫艘恍┕玖鞒谭矫娴氖拢卮鹗钱a(chǎn)品快速迭代,本身需求不可能流程化,只能產(chǎn)品做出來去試水,然后再推翻,如此往復(fù)計(jì)劃跟不上變化快,大致我想要的工作方式并不是這樣,可能有點(diǎn)分歧,也可能由于本來之前本來三面三個(gè)小時(shí)心態(tài)崩潰,可能態(tài)度沒有順著他來,So二面失敗,HR小姐姐招人的傭金也沒了。。
PS:其實(shí)內(nèi)心還是蠻想去的,不過由于之前可能這種工作流程不太適合我,我剛跳出坑,他可能看到了我的猶豫和顧慮吧,所以技術(shù)過了也把我Pass了。。不過佛系的我已經(jīng)無所謂了。。
站酷(ZCOOL)
這家公司是拉勾投的,面試官貌似是幫別的部門招聘,應(yīng)該是做一個(gè)在線教育的項(xiàng)目,聽名字貌似叫“高高手”?遇到答的不好的題面試官都給予了細(xì)致的講解,我覺得收獲蠻大。
具體的問題大概都有:
- Retrofit 如何實(shí)現(xiàn)文件(或圖片上傳)接口是如何定義的
大意要回答multipart/form-data 文件上傳表單中
它會將表單的數(shù)據(jù)處理為一條消息,以標(biāo)簽為單元,用分隔符分開。既可以上傳鍵值對,也可以上傳文件。當(dāng)上傳的字段是文件時(shí),會有Content-Type來表名文件類型;content-disposition,用來說明字段的一些信息;
由于有boundary隔離,所以multipart/form-data既可以上傳文件,也可以上傳鍵值對,它采用了鍵值對的方式,所以可以上傳多個(gè)文件。 - 自定義View的屬性引用attr,styleable里定義的名稱可否與系統(tǒng)已經(jīng)存在的name重復(fù)?當(dāng)然是不可以的,編譯器會預(yù)先檢查系統(tǒng)已經(jīng)存在或者之前已經(jīng)定義重復(fù)的
- 自定義View OnMeasure方法的三種Mode
UNSPECIFIED(未指定),父控件對子控件不加任何束縛,子元素可以得到任意想要的大小,這種MeasureSpec一般是由父控件自身的特性決定的。比如ScrollView,它的子View可以隨意設(shè)置大小,無論多高,都能滾動顯示,這個(gè)時(shí)候,size一般就沒什么意義。
EXACTLY(完全),父控件為子View指定確切大小,希望子View完全按照自己給定尺寸來處理,跟上面的場景1跟2比較相似,這時(shí)的MeasureSpec一般是父控件根據(jù)自身的MeasureSpec跟子View的布局參數(shù)來確定的。一般這種情況下size>0,有個(gè)確定值。
AT_MOST(至多),父控件為子元素指定最大參考尺寸,希望子View的尺寸不要超過這個(gè)尺寸,跟上面場景3比較相似。這種模式也是父控件根據(jù)自身的MeasureSpec跟子View的布局參數(shù)來確定的,一般是子View的布局參數(shù)采用wrap_content的時(shí)候。 - WebView攔截Url和cookie相關(guān)?網(wǎng)頁需要設(shè)置登錄狀態(tài)等情形
- Android中為什么主線程不會因?yàn)長ooper.loop()里的死循環(huán)卡死?
Android應(yīng)用程序的主線程在進(jìn)入消息循環(huán)過程前,會在內(nèi)部創(chuàng)建一個(gè)Linux管道(Pipe),這個(gè)管道的作用是使得Android應(yīng)用程序主線程在消息隊(duì)列為空時(shí)可以進(jìn)入空閑等待狀態(tài),并且使得當(dāng)應(yīng)用程序的消息隊(duì)列有消息需要處理時(shí)喚醒應(yīng)用程序的主線程。 - 解決Android多線程訪問SQLite數(shù)據(jù)庫死鎖問題?database is locked
解決的辦法就是保持sqlite連接單例,保持單個(gè)SqliteOpenHelper實(shí)例,同時(shí)對所有數(shù)據(jù)庫操作的方法添加synchronized關(guān)鍵字。也就是說是讀寫數(shù)據(jù)庫時(shí)存在的同步問題,所以采用單例+同步鎖的方法,并且在每次數(shù)據(jù)庫操作后都關(guān)閉數(shù)據(jù)庫 - Android多進(jìn)程解決單個(gè)進(jìn)程內(nèi)存分配?
微信貌似也用了拆分多進(jìn)程去降低單個(gè)進(jìn)程的heapSize - Android如何實(shí)現(xiàn)大圖加載?
- WeakReference使用場景?
- 在Service里實(shí)現(xiàn)下載如何刷新UI?
- Handler postDelay如何實(shí)現(xiàn)不阻塞UI線程?
1.postDelay()一個(gè)1秒鐘的MyTask任務(wù)、消息進(jìn)隊(duì),MessageQueue開始阻塞,Looper阻塞,mBlocked為true,在enqueueMessage的if中將needWake = mBlocked。
2.然后post一個(gè)新的任務(wù)、消息進(jìn)隊(duì),判斷現(xiàn)在A時(shí)間還沒到、正在阻塞,把新的任務(wù)插入消息隊(duì)列的頭部(MyTask任務(wù)的前面),然后此時(shí)needWake為true調(diào)用nativeWake()方法喚醒線程。
3.MessageQueue.next()方法被喚醒后,重新開始讀取消息鏈表,第一個(gè)消息B無延時(shí),直接返回給Looper;
4.Looper處理完這個(gè)消息再次調(diào)用next()方法,MessageQueue繼續(xù)讀取消息鏈表,第二個(gè)消息A還沒到時(shí)間,計(jì)算一下剩余時(shí)間(假如還剩9秒)繼續(xù)阻塞;
5.直到阻塞時(shí)間到或者下一次有Message進(jìn)隊(duì);
心得
這次面試還算是比較全面的面試吧,無論是深度和廣度問的都很深,面試之后收獲了自己的不足,感覺自己表現(xiàn)還可以,可能由于這個(gè)崗位是剛開始招的,時(shí)間周期會很長不知道會不會給offer... 不過有收獲就是好的~
整理下最近面試的幾個(gè)常見問題
RxJava 變換操作符 map flatMap concatMap buffer?
- 常用的變換操作符
- map:【數(shù)據(jù)類型轉(zhuǎn)換】將被觀察者發(fā)送的事件轉(zhuǎn)換為另一種類型的事件
- flatMap:【化解循環(huán)嵌套和接口嵌套】將被觀察者發(fā)送的事件序列進(jìn)行拆分 & 轉(zhuǎn)換 后合并成一個(gè)新的事件序列,最后再進(jìn)行發(fā)送
- concatMap:【有序】與 flatMap 的 區(qū)別在于,拆分 & 重新合并生成的事件序列 的順序與被觀察者舊序列生產(chǎn)的順序一致
- flatMapIterable:相當(dāng)于對 flatMap 的數(shù)據(jù)進(jìn)行了二次扁平化
- buffer:定期從被觀察者發(fā)送的事件中獲取一定數(shù)量的事件并放到緩存區(qū)中,然后把這些數(shù)據(jù)集合打包發(fā)射
裝飾器模式和代理模式區(qū)別
代理模式,注重對對象某一功能的流程把控和輔助。它可以控制對象做某些事,重心是為了借用對象的功能完成某一流程,而非對象功能如何。
裝飾模式,注重對對象功能的擴(kuò)展,它不關(guān)心外界如何調(diào)用,只注重對對象功能的加強(qiáng),裝飾后還是對象本身。
所以:
對于代理類,如何調(diào)用對象的某一功能是思考重點(diǎn),而不需要兼顧對象的所有功能;
對于裝飾類,如何擴(kuò)展對象的某一功能是思考重點(diǎn),同時(shí)也需要兼顧對象的其它功能,因?yàn)樵僭趺囱b飾,本質(zhì)也是對象本身,要擔(dān)負(fù)起對象應(yīng)有的職責(zé)。
HashMap如何實(shí)現(xiàn)一個(gè)Key對應(yīng)多個(gè)value?
其實(shí)就是Hashmap + ArrayList去實(shí)現(xiàn)的
例:
HashMap<Integer,ArrayList<String>> map = new HashMap<Integer,ArrayList<String>>();
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("xyz");
map.put(100,list);
Android中ClassLoader的種類&特點(diǎn)
- BootClassLoader(Java的BootStrap ClassLoader)
用于加載Android Framework層class文件。 - PathClassLoader(Java的App ClassLoader)
用于加載已經(jīng)安裝到系統(tǒng)中的apk中的class文件。 - DexClassLoader(Java的Custom ClassLoader)
用于加載指定目錄中的class文件。 - BaseDexClassLoader
是PathClassLoader和DexClassLoader的父類。
因?yàn)樽裱p親委派模型,Android中的ClassLoader具有兩個(gè)特點(diǎn):
- 類加載共享
當(dāng)一個(gè)class文件被任何一個(gè)ClassLoader加載過,就不會再被其他ClassLoader加載。 - 類加載隔離
不同ClassLoader加載的class文件肯定不是一個(gè)。舉個(gè)栗子,一些系統(tǒng)層級的class文件在系統(tǒng)初始化的時(shí)候被加載,比如java.net.String,這個(gè)是在應(yīng)用啟動前就被系統(tǒng)加載好的。如果在一個(gè)應(yīng)用里能簡單地用一個(gè)自定義的String類把這個(gè)String類替換掉的話,將有嚴(yán)重的安全問題。
最后
即將入職某影視公司Android Leader崗,面試暫時(shí)告一段落,希望面試心得能幫到大家,祝大家好運(yùn)~