Q:Android中有哪幾種類型的動(dòng)畫(huà)?
- 技術(shù)點(diǎn):動(dòng)畫(huà)類型
- 參考回答: 常見(jiàn)三類動(dòng)畫(huà)
- View動(dòng)畫(huà)(View Animation)/補(bǔ)間動(dòng)畫(huà)(Tween animation):對(duì)View進(jìn)行平移弛槐、縮放懊亡、旋轉(zhuǎn)和透明度變化的動(dòng)畫(huà),不能真正的改變view的位置乎串。應(yīng)用如布局動(dòng)畫(huà)店枣、Activity切換動(dòng)畫(huà)
- 逐幀動(dòng)畫(huà)(Drawable Animation):是View動(dòng)畫(huà)的一種,它會(huì)按照順序播放一組預(yù)先定義好的圖片
- 屬性動(dòng)畫(huà)(Property Animation):對(duì)該類對(duì)象進(jìn)行動(dòng)畫(huà)操作叹誉,真正改變了對(duì)象的屬性
Q:幀動(dòng)畫(huà)在使用時(shí)需要注意什么鸯两?
- 技術(shù)點(diǎn):幀動(dòng)畫(huà)
- 參考回答:使用禎動(dòng)畫(huà)要注意不能使用尺寸過(guò)大的圖片,否則容易造成OOM
Q:View動(dòng)畫(huà)和屬性動(dòng)畫(huà)的區(qū)別长豁?
- 技術(shù)點(diǎn):View動(dòng)畫(huà)钧唐、屬性動(dòng)畫(huà)
- 參考回答:
Q:View動(dòng)畫(huà)為何不能真正改變View的位置?而屬性動(dòng)畫(huà)為何可以匠襟?
- 技術(shù)點(diǎn):View動(dòng)畫(huà)
- 參考回答:View動(dòng)畫(huà)改變的只是View的顯示钝侠,而沒(méi)有改變View的響應(yīng)區(qū)域;而屬性動(dòng)畫(huà)會(huì)通過(guò)反射技術(shù)來(lái)獲取和執(zhí)行屬性的get宅此、set方法机错,從而改變了對(duì)象位置的屬性值。
Q:屬性動(dòng)畫(huà)插值器和估值器的作用父腕?
- 技術(shù)點(diǎn):屬性動(dòng)畫(huà)
- 參考回答:
- 插值器(Interpolator):根據(jù)時(shí)間流逝的百分比計(jì)算出當(dāng)前屬性值改變的百分比弱匪。確定了動(dòng)畫(huà)效果變化的模式,如勻速變化、加速變化等等萧诫。View動(dòng)畫(huà)和屬性動(dòng)畫(huà)均可使用斥难。常用的系統(tǒng)內(nèi)置插值器:
- 線性插值器(LinearInterpolator):勻速動(dòng)畫(huà)
- 加速減速插值器(AccelerateDecelerateInterpolator):動(dòng)畫(huà)兩頭慢中間快
- 減速插值器(DecelerateInterpolator):動(dòng)畫(huà)越來(lái)越慢
- 類型估值器(TypeEvaluator):根據(jù)當(dāng)前屬性改變的百分比計(jì)算出改變后的屬性值。針對(duì)于屬性動(dòng)畫(huà)帘饶,View動(dòng)畫(huà)不需要類型估值器哑诊。常用的系統(tǒng)內(nèi)置的估值器:
- 整形估值器(IntEvaluator)
- 浮點(diǎn)型估值器(FloatEvaluator)
- Color屬性估值器(ArgbEvaluator)
Q:Activity、View及刻、Window三者之間的關(guān)系镀裤?
- 技術(shù)點(diǎn):Activity、View缴饭、Window聯(lián)系
- 思路:圍繞Window是Activity和View的橋梁展開(kāi)
- 參考回答:在Activity啟動(dòng)過(guò)程其中的attach()方法中初始化了PhoneWindow暑劝,而PhoneWindow是Window的唯一實(shí)現(xiàn)類,然后Activity通過(guò)setContentView將View設(shè)置到了PhoneWindow上颗搂,而View通過(guò)WindowManager的addView()担猛、removeView()石洗、updateViewLayout()對(duì)View進(jìn)行管理窄赋。
Q:Window有哪幾種類型?
- 技術(shù)點(diǎn):Window類型
- 參考回答:Window有三種類型:
- 應(yīng)用Window:對(duì)應(yīng)一個(gè)Activity浩蓉。
- 子Window:不能單獨(dú)存在疚察,需附屬特定的父Window蒸走。如Dialog。
- 系統(tǒng)Window: 需申明權(quán)限才能創(chuàng)建貌嫡。如Toast载碌。
Q:Activity創(chuàng)建和Dialog創(chuàng)建過(guò)程的異同?
- 技術(shù)點(diǎn):Window創(chuàng)建
- 參考回答:Dialog的Window創(chuàng)建過(guò)程:
- 創(chuàng)建WindowDialog衅枫。和Activity類似,同樣是通過(guò)PolicyManager.makeNewWindow() 來(lái)實(shí)現(xiàn)弦撩。
- 初始化DecorView并將Dialog的視圖添加到DecorView中去。和Activity類似陪竿,同樣是通過(guò)Window.setContentView() 來(lái)實(shí)現(xiàn)。
- 將DecorView添加到Window中顯示屠橄。和Activity一樣桐绒,都是在自身要出現(xiàn)在前臺(tái)時(shí)才會(huì)將添加Window茉继。
- Dialog.show() 方法:完成DecorView的顯示。
- WindowManager.remoteViewImmediate() 方法:當(dāng)Dialog被dismiss時(shí)移除DecorView威彰。
Q:談?wù)勏C(jī)制Hander评抚?作用?有哪些要素慨代?流程是怎樣的邢笙?
- 技術(shù)點(diǎn):消息機(jī)制
- 參考回答:
- 作用:跨線程通信。當(dāng)子線程中進(jìn)行耗時(shí)操作后需要更新UI時(shí)侍匙,通過(guò)Handler將有關(guān)UI的操作切換到主線程中執(zhí)行氮惯。
- 四要素:
- Message(消息):需要被傳遞的消息,其中包含了消息ID,消息處理對(duì)象以及處理的數(shù)據(jù)等筐骇,由MessageQueue統(tǒng)一列隊(duì)债鸡,最終由Handler處理。
- MessageQueue(消息隊(duì)列):用來(lái)存放Handler發(fā)送過(guò)來(lái)的消息铛纬,內(nèi)部通過(guò)單鏈表的數(shù)據(jù)結(jié)構(gòu)來(lái)維護(hù)消息列表厌均,等待Looper的抽取。
- Handler(處理者):負(fù)責(zé)Message的發(fā)送及處理告唆。通過(guò) Handler.sendMessage() 向消息池發(fā)送各種消息事件棺弊;通過(guò) Handler.handleMessage() 處理相應(yīng)的消息事件。
- Looper(消息泵):通過(guò)Looper.loop()不斷地從MessageQueue中抽取Message擒悬,按分發(fā)機(jī)制將消息分發(fā)給目標(biāo)處理者模她。
具體流程如圖
Handler.sendMessage()
發(fā)送消息時(shí),會(huì)通過(guò)MessageQueue.enqueueMessage()
向MessageQueue中添加一條消息懂牧;- 通過(guò)
Looper.loop()
開(kāi)啟循環(huán)后侈净,不斷輪詢調(diào)用MessageQueue.next()
;- 調(diào)用目標(biāo)
Handler.dispatchMessage()
去傳遞消息僧凤,目標(biāo)Handler收到消息后調(diào)用Handler.handlerMessage()
處理消息畜侦。
Q:為什么系統(tǒng)不建議在子線程訪問(wèn)UI?
- 技術(shù)點(diǎn):UI線程躯保、子線程
- 參考回答:系統(tǒng)不建議在子線程訪問(wèn)UI的原因是旋膳,UI控件非線程安全,在多線程中并發(fā)訪問(wèn)可能會(huì)導(dǎo)致UI控件處于不可預(yù)期的狀態(tài)途事。而不對(duì)UI控件的訪問(wèn)加上鎖機(jī)制的原因有:
- 上鎖會(huì)讓UI控件變得復(fù)雜和低效
- 上鎖后會(huì)阻塞某些進(jìn)程的執(zhí)行
Q:一個(gè)Thread可以有幾個(gè)Looper验懊?幾個(gè)Handler?
- 技術(shù)點(diǎn):Looper尸变、Handler
- 參考回答:一個(gè)Thread只能有一個(gè)Looper义图,可以有多個(gè)Handler
- 引申:更多數(shù)量關(guān)系:Looper有一個(gè)MessageQueue,可以處理來(lái)自多個(gè)Handler的Message召烂;MessageQueue有一組待處理的Message歌溉,這些Message可來(lái)自不同的Handler;Message中記錄了負(fù)責(zé)發(fā)送和處理消息的Handler骑晶;Handler中有Looper和MessageQueue;
Q:如何將一個(gè)Thread線程變成Looper線程草慧?Looper線程有哪些特點(diǎn)桶蛔?
- 技術(shù)點(diǎn):Looper
- 參考回答:通過(guò)Looper.prepare()可將一個(gè)Thread線程轉(zhuǎn)換成Looper線程。Looper線程和普通Thread不同漫谷,它通過(guò)MessageQueue來(lái)存放消息和事件仔雷、Looper.loop()進(jìn)行消息輪詢。
Q:可以在子線程直接new一個(gè)Handler嗎?那該怎么做碟婆?
- 技術(shù)點(diǎn):Handler
- 參考回答:不同于主線程直接new一個(gè)Handler电抚,由于子線程的Looper需要手動(dòng)去創(chuàng)建,在創(chuàng)建Handler時(shí)需要多一些方法:
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();//為子線程創(chuàng)建Looper
new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//子線程消息處理
}
};
Looper.loop(); //開(kāi)啟消息輪詢
}
}).start();
Q:Message可以如何創(chuàng)建竖共?哪種效果更好蝙叛,為什么?
- 技術(shù)點(diǎn):Message
- 參考回答:創(chuàng)建Message對(duì)象的幾種方式:
- Message msg = new Message();
- Message msg = Message.obtain();
- Message msg = handler1.obtainMessage();
后兩種方法都是從整個(gè)Messge池中返回一個(gè)新的Message實(shí)例公给,能有效避免重復(fù)Message創(chuàng)建對(duì)象借帘,因此更鼓勵(lì)這種方式創(chuàng)建Message
Q:這里的ThreadLocal有什么作用?
- 技術(shù)點(diǎn):ThreadLocal
- 參考回答:ThreadLocal類可實(shí)現(xiàn)線程本地存儲(chǔ)的功能淌铐,把共享數(shù)據(jù)的可見(jiàn)范圍限制在同一個(gè)線程之內(nèi)肺然,無(wú)須同步就能保證線程之間不出現(xiàn)數(shù)據(jù)爭(zhēng)用的問(wèn)題,這里可理解為T(mén)hreadLocal幫助Handler找到本線程的Looper腿准。
- 底層數(shù)據(jù)結(jié)構(gòu):每個(gè)線程的Thread對(duì)象中都有一個(gè)ThreadLocalMap對(duì)象际起,它存儲(chǔ)了一組以ThreadLocal.threadLocalHashCode為key、以本地線程變量為value的鍵值對(duì)吐葱,而ThreadLocal對(duì)象就是當(dāng)前線程的ThreadLocalMap的訪問(wèn)入口街望,也就包含了一個(gè)獨(dú)一無(wú)二的threadLocalHashCode值,通過(guò)這個(gè)值就可以在線程鍵值值對(duì)中找回對(duì)應(yīng)的本地線程變量唇撬。
Q:主線程中Looper的輪詢死循環(huán)為何沒(méi)有阻塞主線程它匕?
- 技術(shù)點(diǎn):Looper
- 參考回答:Android是依靠事件驅(qū)動(dòng)的,通過(guò)Loop.loop()不斷進(jìn)行消息循環(huán)窖认,可以說(shuō)Activity的生命周期都是運(yùn)行在 Looper.loop()的控制之下豫柬,一旦退出消息循環(huán),應(yīng)用也就退出了扑浸。而所謂的導(dǎo)致ANR多是因?yàn)槟硞€(gè)事件在主線程中處理時(shí)間太耗時(shí)烧给,因此只能說(shuō)是對(duì)某個(gè)消息的處理阻塞了Looper.loop(),反之則不然喝噪。
Q:使用Hanlder的postDealy()后消息隊(duì)列會(huì)發(fā)生什么變化础嫡?
- 技術(shù)點(diǎn):Handler
- 參考回答:post delay的Message并不是先等待一定時(shí)間再放入到MessageQueue中,而是直接進(jìn)入并阻塞當(dāng)前線程酝惧,然后將其delay的時(shí)間和隊(duì)頭的進(jìn)行比較榴鼎,按照觸發(fā)時(shí)間進(jìn)行排序,如果觸發(fā)時(shí)間更近則放入隊(duì)頭晚唇,保證隊(duì)頭的時(shí)間最小巫财、隊(duì)尾的時(shí)間最大。此時(shí)哩陕,如果隊(duì)頭的Message正是被delay的平项,則將當(dāng)前線程堵塞一段時(shí)間赫舒,直到等待足夠時(shí)間再喚醒執(zhí)行該Message,否則喚醒后直接執(zhí)行闽瓢。
Q:Android中還了解哪些方便線程切換的類接癌?
- 技術(shù)點(diǎn):線程通信
- 參考回答:對(duì)Handler進(jìn)一步的封裝的幾個(gè)類:
- AsyncTask:底層封裝了線程池和Handler,便于執(zhí)行后臺(tái)任務(wù)以及在子線程中進(jìn)行UI操作扣讼。
- HandlerThread:一種具有消息循環(huán)的線程缺猛,其內(nèi)部可使用Handler。
- IntentService:是一種異步届谈、會(huì)自動(dòng)停止的服務(wù)枯夜,內(nèi)部采用HandlerThread。
- 引申:更多是對(duì)消息機(jī)制的理解
Q:AsyncTask相比Handler有什么優(yōu)點(diǎn)艰山?不足呢湖雹?
- 技術(shù)點(diǎn):AsyncTask、Handler
- 參考回答:
- Handler機(jī)制存在的問(wèn)題:多任務(wù)同時(shí)執(zhí)行時(shí)不易精確控制線程曙搬。
- 引入AsyncTask的好處:創(chuàng)建異步任務(wù)更簡(jiǎn)單摔吏,直接繼承它可方便實(shí)現(xiàn)后臺(tái)異步任務(wù)的執(zhí)行和進(jìn)度的回調(diào)更新UI,而無(wú)需編寫(xiě)任務(wù)線程和Handler實(shí)例就能完成相同的任務(wù)纵装。
Q:使用AsyncTask需要注意什么征讲?
- 技術(shù)點(diǎn):AsyncTask
- 參考回答:
- 不要直接調(diào)用onPreExecute()、doInBackground()橡娄、onProgressUpdate()诗箍、onPostExecute()和onCancelled()方法
- 一個(gè)異步對(duì)象只能調(diào)用一次execute()方法
- 引申:談?wù)凙syncTask初始化、五個(gè)核心方法如何配合進(jìn)而體現(xiàn)Handler的作用
Q:AsyncTask中使用的線程池大型彀Α滤祖?
- 技術(shù)點(diǎn):AsyncTask
- 參考回答:在AsyncTask內(nèi)部實(shí)現(xiàn)有兩個(gè)線程池:
- SerialExecutor:用于任務(wù)的排隊(duì),默認(rèn)是串行的線程池瓶籽,在3.0以前核心線程數(shù)為5匠童、線程池大小為128,而3.0以后變?yōu)橥粫r(shí)間只能處理一個(gè)任務(wù)
- THREAD_POOL_EXECUTOR:用于真正執(zhí)行任務(wù)塑顺。
- 引申:談?wù)剬?duì)線程池的理解
Q:HandlerThread有什么特點(diǎn)汤求?
- 技術(shù)點(diǎn):HandlerThread
- 參考回答:HandlerThread是一個(gè)線程類,它繼承自Thread严拒。與普通Thread不同扬绪,HandlerThread具有消息循環(huán)的效果,這是因?yàn)樗鼉?nèi)部
HandlerThread.run()
方法中有Looper裤唠,能通過(guò)Looper.prepare()
來(lái)創(chuàng)建消息隊(duì)列挤牛,并通過(guò)Looper.loop()
來(lái)開(kāi)啟消息循環(huán)。
Q:快速實(shí)現(xiàn)子線程使用Handler
- 技術(shù)點(diǎn):HandlerThread
- 思路:不同于之前手動(dòng)在子線程創(chuàng)建Looper再構(gòu)建Handler的想法巧骚,這里從HandlerThread角度去快速實(shí)現(xiàn)在子線程使用Handler
- 參考回答:HandlerThread實(shí)現(xiàn)方法
- 實(shí)例化一個(gè)HandlerThread對(duì)象赊颠,參數(shù)是該線程的名稱;
- 通過(guò) HandlerThread.start()開(kāi)啟線程劈彪;
- 實(shí)例化一個(gè)Handler并傳入HandlerThread中的looper對(duì)象竣蹦,使得與HandlerThread綁定;
- 利用Handler即可執(zhí)行異步任務(wù)沧奴;
- 當(dāng)不需要HandlerThread時(shí)痘括,通過(guò)HandlerThread.quit()/quitSafely()方法來(lái)終止線程的執(zhí)行。
Q:IntentService的特點(diǎn)滔吠?
- 技術(shù)點(diǎn):IntentService
- 思路:和普通線程和普通Service比較突出其特點(diǎn)
- 參考回答: 不同于線程纲菌,IntentService是服務(wù),優(yōu)先級(jí)比線程高疮绷,更不容易被系統(tǒng)殺死翰舌,因此較適合執(zhí)行一些高優(yōu)先級(jí)的后臺(tái)任務(wù);不同于普通Service冬骚,IntentService可自動(dòng)創(chuàng)建子線程來(lái)執(zhí)行任務(wù)椅贱,且任務(wù)執(zhí)行完畢后自動(dòng)退出。
Q:為何不用bindService方式創(chuàng)建IntentService只冻?
- 技術(shù)點(diǎn):IntentService
- 思路:從底層實(shí)現(xiàn)出發(fā)
- 參考回答:IntentService的工作原理是庇麦,在IntentService的onCreate()里會(huì)創(chuàng)建一個(gè)HandlerThread,并利用其內(nèi)部的Looper實(shí)例化一個(gè)ServiceHandler對(duì)象喜德;而這個(gè)ServiceHandler用于處理消息的handleMessage()方法會(huì)去調(diào)用IntentService的onHandleIntent()山橄,這也是為什么可在該方法中處理后臺(tái)任務(wù)的邏輯;當(dāng)有Intent任務(wù)請(qǐng)求時(shí)會(huì)把Intent封裝到Message舍悯,然后ServiceHandler會(huì)把消息發(fā)送出航棱,而發(fā)送消息是在onStartCommand()完成的,只能通過(guò)startService()才可走該生命周期方法贱呐,因此不能通過(guò)bindService創(chuàng)建IntentService丧诺。
Q:線程池的好處、原理奄薇、類型驳阎?
- 技術(shù)點(diǎn):線程池
- 參考回答:
- (1)線程池的好處:
- 重用線程池中的線程,避免線程的創(chuàng)建和銷毀帶來(lái)的性能消耗馁蒂;
- 有效控制線程池的最大并發(fā)數(shù)呵晚,避免大量的線程之間因互相搶占系統(tǒng)資源而導(dǎo)致阻塞現(xiàn)象;
- 進(jìn)行線程管理沫屡,提供定時(shí)/循環(huán)間隔執(zhí)行等功能
- (2)線程池的分類:
- FixThreadPool:線程數(shù)量固定的線程池饵隙,所有線程都是核心線程,當(dāng)線程空閑時(shí)不會(huì)被回收沮脖;能快速響應(yīng)外界請(qǐng)求金矛。
- CachedThreadPool:線程數(shù)量不定的線程池(最大線程數(shù)為Integer.MAX_VALUE)芯急,只有非核心線程,空閑線程有超時(shí)機(jī)制驶俊,超時(shí)回收娶耍;適合于執(zhí)行大量的耗時(shí)較少的任務(wù)
- ScheduledThreadPool:核心線程數(shù)量固定,非核心線程數(shù)量不定饼酿;可進(jìn)行定時(shí)任務(wù)和固定周期的任務(wù)榕酒。
- SingleThreadExecutor:只有一個(gè)核心線程,可確保所有的任務(wù)都在同一個(gè)線程中按順序執(zhí)行故俐;好處是無(wú)需處理線程同步問(wèn)題想鹰。
- (3)線程池的原理:實(shí)際上通過(guò)ThreadPoolExecutor并通過(guò)一系列參數(shù)來(lái)配置各種各樣的線程池,具體的參數(shù)有:
- corePoolSize核心線程數(shù):一般會(huì)在線程中一直存活
- maximumPoolSize最大線程數(shù):當(dāng)活動(dòng)線程數(shù)達(dá)到這個(gè)數(shù)值后药版,后續(xù)的任務(wù)將會(huì)被阻塞
- keepAliveTime非核心線程超時(shí)時(shí)間:超過(guò)這個(gè)時(shí)長(zhǎng)辑舷,閑置的非核心線程就會(huì)被回收
- unit:用于指定keepAliveTime參數(shù)的時(shí)間單位
- workQueue任務(wù)隊(duì)列:通過(guò)線程池的
execute()
方法提交的Runnable對(duì)象會(huì)存儲(chǔ)在這個(gè)參數(shù)中。- threadFactory:線程工廠刚陡,可創(chuàng)建新線程
- handler:在線程池?zé)o法執(zhí)行新任務(wù)時(shí)進(jìn)行調(diào)度
- 引申:使用Executors各個(gè)方法創(chuàng)建線程池的弊端
Q:ThreadPoolExecutor的工作策略惩妇?
- 技術(shù)點(diǎn):線程池
- 參考回答:ThreadPoolExecutor的默認(rèn)工作策略:
- 若程池中的線程數(shù)量未達(dá)到核心線程數(shù),則會(huì)直接啟動(dòng)一個(gè)核心線程執(zhí)行任務(wù)筐乳。
- 若線程池中的線程數(shù)量已達(dá)到或者超過(guò)核心線程數(shù)量歌殃,則任務(wù)會(huì)被插入到任務(wù)列表等待執(zhí)行。
- 若任務(wù)無(wú)法插入到任務(wù)列表中蝙云,往往由于任務(wù)列表已滿氓皱,此時(shí)如果
- 線程數(shù)量未達(dá)到線程池最大線程數(shù),則會(huì)啟動(dòng)一個(gè)非核心線程執(zhí)行任務(wù)勃刨;
- 線程數(shù)量已達(dá)到線程池規(guī)定的最大值波材,則拒絕執(zhí)行此任務(wù),ThreadPoolExecutor會(huì)調(diào)用RejectedExecutionHandler的rejectedExecution方法來(lái)通知調(diào)用者身隐。
- 引申:ThreadPoolExecutor的拒絕策略
Q:什么是ANR廷区?什么情況會(huì)出現(xiàn)ANR?如何避免贾铝?在不看代碼的情況下如何快速定位出現(xiàn)ANR問(wèn)題所在隙轻?
- 技術(shù)點(diǎn):ANR
- 思路:
- 參考回答:
- ANR(Application Not Responding,應(yīng)用無(wú)響應(yīng)):當(dāng)操作在一段時(shí)間內(nèi)系統(tǒng)無(wú)法處理時(shí)垢揩,會(huì)在系統(tǒng)層面會(huì)彈出ANR對(duì)話框
- 產(chǎn)生ANR可能是因?yàn)?s內(nèi)無(wú)響應(yīng)用戶輸入事件玖绿、10s內(nèi)未結(jié)束B(niǎo)roadcastReceiver、20s內(nèi)未結(jié)束Service
- 想要避免ANR就不要在主線程做耗時(shí)操作叁巨,而是通過(guò)開(kāi)子線程斑匪,方法比如繼承Thread或?qū)崿F(xiàn)Runnable接口、使用AsyncTask锋勺、IntentService蚀瘸、HandlerThread等
- 引申:快讀定位ANR方法:使用命令導(dǎo)出ANR日志狡蝶,并分析關(guān)鍵信息,詳見(jiàn)ANR問(wèn)題一般解決思路
Q:加載圖片的時(shí)候需要注意什么贮勃?
- 技術(shù)點(diǎn):Bitmap高效加載
- 參考回答:
- 直接加載大容量的高清Bitmap很容易出現(xiàn)顯示不完整牢酵、內(nèi)存溢出OOM的問(wèn)題,所以最好按一定的采樣率將圖片縮小后再加載進(jìn)來(lái)
- 為減少流量消耗衙猪,可對(duì)圖片采用內(nèi)存緩存策略,又為了避免圖片占用過(guò)多內(nèi)存導(dǎo)致內(nèi)存溢出布近,最好以軟引用方式持有圖片
- 如果還需要網(wǎng)上下載圖片垫释,注意要開(kāi)子線程去做下載的耗時(shí)操作
Q:LRU算法的原理?
- 技術(shù)點(diǎn):LRU算法
- 參考回答:為減少流量消耗撑瞧,可采用緩存策略棵譬。常用的緩存算法是LRU(Least Recently Used):
- 核心思想:當(dāng)緩存滿時(shí), 會(huì)優(yōu)先淘汰那些近期最少使用的緩存對(duì)象。主要是兩種方式:
- LruCache(內(nèi)存緩存):LruCache類是一個(gè)線程安全的泛型類:內(nèi)部采用一個(gè)
LinkedHashMap
以強(qiáng)引用的方式存儲(chǔ)外界的緩存對(duì)象预伺,并提供get
和put
方法來(lái)完成緩存的獲取和添加操作订咸,當(dāng)緩存滿時(shí)會(huì)移除較早使用的緩存對(duì)象,再添加新的緩存對(duì)象酬诀。- DiskLruCache(磁盤(pán)緩存): 通過(guò)將緩存對(duì)象寫(xiě)入文件系統(tǒng)從而實(shí)現(xiàn)緩存效果
- 引申:感興趣可了解具體實(shí)現(xiàn)算法
Q:項(xiàng)目中如何做性能優(yōu)化的脏嚷?
- 技術(shù)點(diǎn):性能優(yōu)化實(shí)例
- 思路:舉例說(shuō)明項(xiàng)目注意了哪些方面的性能優(yōu)化,如布局優(yōu)化瞒御、繪制優(yōu)化父叙、內(nèi)存泄漏優(yōu)化、 響應(yīng)速度優(yōu)化肴裙、列表優(yōu)化趾唱、Bitmap優(yōu)化、 線程優(yōu)化......
Q:了解哪些性能優(yōu)化的工具蜻懦?
- 技術(shù)點(diǎn):性能優(yōu)化工具
- 思路:做項(xiàng)目時(shí)是否使用過(guò)的系統(tǒng)自帶的性能優(yōu)化工具甜癞?公司是否有自己的性能優(yōu)化工具?實(shí)現(xiàn)原理怎樣的宛乃?
Q:布局上如何優(yōu)化悠咱?
- 技術(shù)點(diǎn):布局優(yōu)化
- 參考回答:布局優(yōu)化的核心就是盡量減少布局文件的層級(jí),常見(jiàn)的方式有:
- 多嵌套情況下可使用RelativeLayout減少嵌套烤惊。
- 布局層級(jí)相同的情況下使用LinearLayout乔煞,它比RelativeLayout更高效。
- 使用
<include>
標(biāo)簽重用布局柒室、<merge>
標(biāo)簽減少層級(jí)渡贾、<ViewStub>
標(biāo)簽懶加載。
Q:內(nèi)存泄漏是什么雄右?為什么會(huì)發(fā)生空骚?常見(jiàn)哪些內(nèi)存泄漏的例子纺讲?都是怎么解決的?
- 技術(shù)點(diǎn):內(nèi)存泄漏
- 參考回答:內(nèi)存泄漏(Memory Leak)是指程序在申請(qǐng)內(nèi)存后囤屹,無(wú)法釋放已申請(qǐng)的內(nèi)存空間熬甚。簡(jiǎn)單地說(shuō),發(fā)生內(nèi)存泄漏是由于長(zhǎng)周期對(duì)象持有對(duì)短周期對(duì)象的引用肋坚,使得短周期對(duì)象不能被及時(shí)回收乡括。常見(jiàn)的幾個(gè)例子和解決辦法:
- 單例模式導(dǎo)致的內(nèi)存泄漏:?jiǎn)卫齻魅雲(yún)?shù)this來(lái)自Activity,使得持有對(duì)Activity的引用智厌。
- 解決辦法:傳參context.getApplicationContext()
- Handler導(dǎo)致的內(nèi)存泄漏:Message持有對(duì)Handler的引用诲泌,而非靜態(tài)內(nèi)部類的Handler又隱式持有對(duì)外部類Activity的引用,使得引用關(guān)系會(huì)保持至消息得到處理铣鹏,從而阻止了Activity的回收敷扫。
- 解決辦法:使用靜態(tài)內(nèi)部類+WeakReference弱引用;當(dāng)外部類結(jié)束生命周期時(shí)清空消息隊(duì)列诚卸。
- 線程導(dǎo)致的內(nèi)存泄漏:AsyncTask/Runnable以匿名內(nèi)部類的方式存在葵第,會(huì)隱式持有對(duì)所在Activity的引用。
- 解決辦法:將AsyncTask和Runnable設(shè)為靜態(tài)內(nèi)部類或獨(dú)立出來(lái)合溺;在線程內(nèi)部采用弱引用保存Context引用
- 資源未關(guān)閉導(dǎo)致的內(nèi)存泄漏:未及時(shí)注銷資源導(dǎo)致內(nèi)存泄漏卒密,如BraodcastReceiver、File棠赛、Cursor栅受、Stream、Bitmap等恭朗。
- 解決辦法:在Activity銷毀的時(shí)候要及時(shí)關(guān)閉或者注銷屏镊。
- BraodcastReceiver:調(diào)用
unregisterReceiver()
注銷;- Cursor痰腮,Stream而芥、File:調(diào)用
close()
關(guān)閉矾屯;- 動(dòng)畫(huà):在
Activity.onDestroy()
中調(diào)用Animator.cancel()
停止動(dòng)畫(huà)- 引申:談?wù)勴?xiàng)目中是如何注意內(nèi)存泄漏的問(wèn)題
Q:內(nèi)存泄漏和內(nèi)存溢出的區(qū)別
- 技術(shù)點(diǎn):內(nèi)存泄漏导俘、內(nèi)存溢出
- 參考回答:
- 內(nèi)存泄漏(Memory Leak)是指程序在申請(qǐng)內(nèi)存后周循,無(wú)法釋放已申請(qǐng)的內(nèi)存空間忘蟹。是造成應(yīng)用程序OOM的主要原因之一。
- 內(nèi)存溢出(out of memory)是指程序在申請(qǐng)內(nèi)存時(shí)喉镰,沒(méi)有足夠的內(nèi)存空間供其使用签杈。
Q:什么情況會(huì)導(dǎo)致內(nèi)存溢出规脸?
- 技術(shù)點(diǎn):內(nèi)存溢出
- 參考回答:內(nèi)存泄漏是導(dǎo)致內(nèi)存溢出的主要原因翘狱;直接加載大圖片也易造成內(nèi)存溢出
- 引申:談?wù)勅绾伪苊鈨?nèi)存溢出(如何避免內(nèi)存泄漏秘案、避免直接加載大圖片)
開(kāi)源框架(略)
谷歌新動(dòng)態(tài)
Q:是否了解和使用過(guò)谷歌推出的新技術(shù)?
Q:有了解剛發(fā)布的Androidx.0的特性嗎?
Q:Kotlin對(duì)Java做了哪些優(yōu)化阱高?
- 可能意圖:了解候選者對(duì)谷歌&安卓的關(guān)注度赚导、共同探討對(duì)新技術(shù)的看法、學(xué)習(xí)主動(dòng)性赤惊、平時(shí)學(xué)習(xí)習(xí)慣
- 思路:谷歌的安卓官方網(wǎng)站(中文版):https://developer.android.google.cn吼旧,了解最新動(dòng)態(tài)
1.2 Java
- 基礎(chǔ)
Q:面向?qū)ο缶幊痰乃拇筇匦约捌浜x?
- 技術(shù)點(diǎn):面向?qū)ο缶幊烫攸c(diǎn)
- 思路:分條簡(jiǎn)述每個(gè)特性的含義
- 參考回答:
- 抽象:對(duì)現(xiàn)實(shí)世界的事物進(jìn)行概括未舟,抽象為在計(jì)算機(jī)虛擬世界中有意義的實(shí)體
- 封裝:將某事物的屬性和行為包裝到對(duì)象中圈暗,構(gòu)成一個(gè)不可分割的獨(dú)立實(shí)體,數(shù)據(jù)被保護(hù)在抽象數(shù)據(jù)類型的內(nèi)部裕膀,并且盡可能地隱藏內(nèi)部的細(xì)節(jié)厂置,只保留一些對(duì)外接口使之與外部發(fā)生聯(lián)系
- 繼承:子類繼承父類,不僅可以有父類原有的方法和屬性魂角,也可以增加自己的或者重寫(xiě)父類的方法及屬性
- 多態(tài):允許不同類的對(duì)象對(duì)同一消息做出各自的響應(yīng)
Q:String、StringBuffer和StringBuilder的區(qū)別智绸?
- 技術(shù)點(diǎn):String
- 參考回答:
- String是字符串常量野揪,而StringBuffer、StringBuilder都是字符串變量瞧栗,即String對(duì)象一創(chuàng)建后不可更改斯稳,而后兩者的對(duì)象是可更改的:
- StringBuffer是線程安全的,而StringBuilder是非線程安全的迹恐,這是由于StringBuffer對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖
- String更適用于少量的字符串操作的情況挣惰,StringBuilder適用于單線程下在字符緩沖區(qū)進(jìn)行大量操作的情況,StringBuffer適用于多線程下在字符緩沖區(qū)進(jìn)行大量操作的情況
Q:String a=""和String a=new String("")的的關(guān)系和異同殴边?
- 技術(shù)點(diǎn):String
- 參考回答:
- 通過(guò)String a=""直接賦值的方式得到的是一個(gè)字符串常量憎茂,存在于常量池;注意锤岸,相同內(nèi)容的字符串在常量池中只有一個(gè)竖幔,即如果池已包含內(nèi)容相等的字符串會(huì)返回池中的字符串拳氢,反之會(huì)將該字符串放入池中
- 通過(guò)new String("")創(chuàng)建的字符串不是常量是實(shí)例對(duì)象,會(huì)在堆內(nèi)存開(kāi)辟空間并存放數(shù)據(jù)蛋铆,且每個(gè)實(shí)例對(duì)象都有自己的地址空間
- 引申:對(duì)于用String a=""和String a=new String("")兩種方式定義的字符串馋评,判斷使用equals()、"=="比較結(jié)果是什么
Q:Object的equal()和==的區(qū)別刺啦?
- 技術(shù)點(diǎn):equal()留特、==
- 參考回答:
- equals():是Object的公有方法,具體含義取決于如何重寫(xiě),比如String的equals()比較的是兩個(gè)字符串的內(nèi)容是否相同
- "==" :對(duì)于基本數(shù)據(jù)類型來(lái)說(shuō)磕秤,比較的是兩個(gè)變量值是夠是否相等乳乌,對(duì)于引用類型來(lái)說(shuō),比較的是兩個(gè)對(duì)象的內(nèi)存地址是否相同
- 引申:對(duì)于用String a=""和String a=new String("")兩種方式定義的字符串市咆,判斷使用equals()汉操、"=="比較結(jié)果是什么
Q:裝箱、拆箱什么含義蒙兰?
- 技術(shù)點(diǎn):裝箱磷瘤、拆箱
- 參考回答:裝箱就是自動(dòng)將基本數(shù)據(jù)類型轉(zhuǎn)換為包裝器類型,拆箱就是自動(dòng)將包裝器類型轉(zhuǎn)換為基本數(shù)據(jù)類型
Q:int和Integer的區(qū)別搜变?
- 技術(shù)點(diǎn):基本數(shù)據(jù)類型采缚、引用類型
- 參考回答:
- Integer是int的包裝類,int則是java的一種基本數(shù)據(jù)類型
- Integer變量必須實(shí)例化后才能使用挠他,而int變量不需要
- Integer實(shí)際是對(duì)象的引用殖侵,當(dāng)new一個(gè)Integer時(shí)楞陷,實(shí)際上是生成一個(gè)指針指向此對(duì)象;而int則是直接存儲(chǔ)數(shù)據(jù)值
- Integer的默認(rèn)值是null艾凯,int的默認(rèn)值是0
Q:遇見(jiàn)過(guò)哪些運(yùn)行時(shí)異常?異常處理機(jī)制知道哪些沧竟?
- 技術(shù)點(diǎn):Java異常機(jī)制
- 思路:對(duì)Throwable異常進(jìn)行分類說(shuō)明每種異常的特點(diǎn)和常見(jiàn)問(wèn)題,簡(jiǎn)述幾種常見(jiàn)異常處理機(jī)制糕非,詳見(jiàn)Java基礎(chǔ)之異常機(jī)制
- 參考回答:
- (1) Throwable繼承層次結(jié)構(gòu),可見(jiàn)分成兩大類Error和Exception:
- Error(錯(cuò)誤):指程序無(wú)法恢復(fù)的異常情況篱昔,表示運(yùn)行應(yīng)用程序中較嚴(yán)重的問(wèn)題;發(fā)生于虛擬機(jī)自身穗椅、或者在虛擬機(jī)試圖執(zhí)行應(yīng)用時(shí),如Virtual MachineError(Java虛擬機(jī)運(yùn)行錯(cuò)誤)袍镀、NoClassDefFoundError(類定義錯(cuò)誤)明也;屬于不可查異常,即不強(qiáng)制程序員必須處理撑刺,即使不處理也不會(huì)出現(xiàn)語(yǔ)法錯(cuò)誤。
- Exception(異常):指程序有可能恢復(fù)的異常情況冕屯,表示程序本身可以處理的異常。又分兩大類:
- RuntimeException(運(yùn)行時(shí)異常):由程序自身的問(wèn)題導(dǎo)致產(chǎn)生的異常丘喻;如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標(biāo)越界異常);屬于不可查異常翠语。
- 非運(yùn)行時(shí)異常:由程序外部的問(wèn)題引起的異常点骑;除了RuntimeException以外的異常,如FileNotFoundException(文件不存在異常);屬于可查異常晚缩,即強(qiáng)制程序員必須進(jìn)行處理待笑,如果不進(jìn)行處理則會(huì)出現(xiàn)語(yǔ)法錯(cuò)誤寞缝。
- (2)常見(jiàn)的異常處理機(jī)制有:
- 捕捉異常:由系統(tǒng)自動(dòng)拋出異常我纪,即try捕獲異常->catch處理異常->finally 最終處理
- 拋出異常:在方法中將異常對(duì)象顯性地拋出券犁,之后異常會(huì)沿著調(diào)用層次向上拋出,交由調(diào)用它的方法來(lái)處理。配合throws聲明拋出的異常和throw拋出異常
- 自定義異常:繼承Execption類或其子類
Q:什么是反射褂删,有什么作用和應(yīng)用?
- 技術(shù)點(diǎn):反射
- 思路:簡(jiǎn)述反射的定義轴术、功能和應(yīng)用盖袭,詳見(jiàn)Java基礎(chǔ)之泛型&反射
- 參考回答:
- 含義:在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類都能知道它的所有屬性和方法宣肚,對(duì)于任何一個(gè)對(duì)象都能夠調(diào)用它的任何一個(gè)方法和屬性想罕。
- 功能:動(dòng)態(tài)性,體現(xiàn)在:在運(yùn)行時(shí)判斷任意一個(gè)類所具有的屬性和方法霉涨; 在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類按价;在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象;在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法笙瑟;生成動(dòng)態(tài)代理
- 應(yīng)用:反射&泛型
- 引申:是否在項(xiàng)目中使用過(guò)反射機(jī)制,有什么優(yōu)缺點(diǎn)
Q:什么是內(nèi)部類秉宿?有什么作用?靜態(tài)內(nèi)部類和非靜態(tài)內(nèi)部類的區(qū)別技潘?
- 技術(shù)點(diǎn):內(nèi)部類
- 思路:
- 參考回答:內(nèi)部類就是定義在另外一個(gè)類里面的類。它隱藏在外部類中鸯隅,封裝性更強(qiáng)蒜危,不允許除外部類外的其他類訪問(wèn)它晃酒;但它可直接訪問(wèn)外部類的成員山析。靜態(tài)內(nèi)部類和非靜態(tài)內(nèi)部類的區(qū)別有:
- 靜態(tài)內(nèi)部類是指被聲明為static的內(nèi)部類,可不依賴外部類實(shí)例化罐栈;而非靜態(tài)內(nèi)部類需要通過(guò)生成外部類來(lái)間接生成琳疏。
- 靜態(tài)內(nèi)部類只能訪問(wèn)外部類的靜態(tài)成員變量和靜態(tài)方法,而非靜態(tài)內(nèi)部類由于持有對(duì)外部類的引用俐筋,可以訪問(wèn)外部類的所用成員
- 引申:談?wù)勀涿麅?nèi)部類
Q:final闷哆、finally屈留、finalize()分別表示什么含義
- 技術(shù)點(diǎn):final蔓挖、finally树埠、finalize()
- 參考回答:
- final關(guān)鍵字表示不可更改糠馆,具體體現(xiàn)在:
- final修飾的變量必須要初始化,且賦初值后不能再重新賦值
- final修飾的方法不能被子類重寫(xiě)
- final修飾的類不能被繼承
- finally:和try怎憋、catch成套使用進(jìn)行異常處理又碌,無(wú)論是否捕獲或處理異常,finally塊里的語(yǔ)句都會(huì)被執(zhí)行绊袋,在以下4種特殊情況下毕匀,finally塊才不會(huì)被執(zhí)行:
- 在finally語(yǔ)句塊中發(fā)生了異常
- 在前面的代碼中用了
System.exit()
退出程序- 程序所在的線程死亡
- 關(guān)閉CPU
- finalize():是Object中的方法,當(dāng)垃圾回收器將回收對(duì)象從內(nèi)存中清除出去之前會(huì)調(diào)用finalize()癌别,但此時(shí)并不代表該回收對(duì)象一定會(huì)“死亡”皂岔,還有機(jī)會(huì)“逃脫”
Q:重寫(xiě)和重載的區(qū)別?
- 技術(shù)點(diǎn):重寫(xiě)展姐、重載
- 參考回答:重寫(xiě)表示子類重寫(xiě)父類的方法躁垛;重載表示有多個(gè)同名函數(shù)同時(shí)存在,區(qū)別在于有不同的參數(shù)個(gè)數(shù)或類型
- 引申:談?wù)剟?dòng)態(tài)分派和靜態(tài)分派
Q:抽象類和接口的異同圾笨?
- 技術(shù)點(diǎn):抽象類教馆、接口
- 參考回答:
- 使用上的區(qū)別:一個(gè)類只能繼承一個(gè)抽象類卻可以實(shí)現(xiàn)多個(gè)接口
- 設(shè)計(jì)上的區(qū)別:接口是對(duì)行為的抽象,無(wú)需有子類的前提擂达,是自上而下的設(shè)計(jì)理念土铺;抽象類是對(duì)類的抽象,建立于相似子類之上,是自下而上的設(shè)計(jì)理念
Q:為什么匿名內(nèi)部類中使用局部變量要用final修飾舒憾?
- 技術(shù)點(diǎn):匿名內(nèi)部類
- 參考回答:一方面,由于方法中的局部變量的生命周期很短穗熬,一旦方法結(jié)束變量就要被銷毀镀迂,為了保證在內(nèi)部類中能找到外部局部變量,通過(guò)final關(guān)鍵字可得到一個(gè)外部變量的引用唤蔗;另一方面探遵,通過(guò)final關(guān)鍵字也不會(huì)在內(nèi)部類去做修改該變量的值,保護(hù)了數(shù)據(jù)的一致性妓柜。
Q:Object有哪些公有方法箱季?
- 技術(shù)點(diǎn):Object
- 思路:列舉常見(jiàn)的幾個(gè)公有方法
- 參考回答:
- equals(): 和==作用相似
- hashCode():用于哈希查找,重寫(xiě)了equals()一般都要重寫(xiě)該方法
- getClass(): 獲取Class對(duì)象
- wait():讓當(dāng)前線程進(jìn)入等待狀態(tài)棍掐,并釋放它所持有的鎖
- notify()¬ifyAll(): 喚醒一個(gè)(所有)正處于等待狀態(tài)的線程
- toString():轉(zhuǎn)換成字符串
- 引申:equals()和==的不同藏雏、在synchronized 同步代碼塊里wait()和notify()¬ifyAll()如何配合、hashCode()和equals()的關(guān)系作煌、獲取Class對(duì)象還有什么方法
Q:Java集合框架中有哪些類掘殴?都有什么特點(diǎn)
- 技術(shù)點(diǎn):集合框架
- 思路:分條解釋每種類的特點(diǎn)
- 參考回答:可將Java集合框架大致可分為Set、List粟誓、Queue 和Map四種體系
- Set:代表無(wú)序奏寨、不可重復(fù)的集合,常見(jiàn)的類如HashSet鹰服、TreeSet
- List:代表有序病瞳、可重復(fù)的集合,常見(jiàn)的類如動(dòng)態(tài)數(shù)組ArrayList悲酷、雙向鏈表LinkedList套菜、可變數(shù)組Vector
- Map:代表具有映射關(guān)系的集合,常見(jiàn)的類如HashMap设易、LinkedHashMap笼踩、TreeMap
- Queue:代表一種隊(duì)列集合
Q:集合、數(shù)組亡嫌、泛型的關(guān)系嚎于,并比較
- 技術(shù)點(diǎn):集合、數(shù)組挟冠、泛型
- 參考回答:
- (1)集合和數(shù)組的區(qū)別:
- 數(shù)組元素可以是基本類型于购,也可以是對(duì)象;數(shù)組長(zhǎng)度限定知染;數(shù)組只能存儲(chǔ)一種類型的數(shù)據(jù)元素
- 集合元素只能是對(duì)象肋僧;集合長(zhǎng)度可變;集合可存儲(chǔ)不同種的數(shù)據(jù)元素
- (2)泛型相比與集合的好處在于它安全簡(jiǎn)單。具體體現(xiàn)在提供編譯時(shí)的強(qiáng)類型檢查嫌吠,而不用等到運(yùn)行止潘;可避免類類型強(qiáng)制轉(zhuǎn)換
Q:ArrayList和LinkList的區(qū)別?
- 技術(shù)點(diǎn):List對(duì)比
- 參考回答:
- ArrayList的底層結(jié)構(gòu)是數(shù)組辫诅,可用索引實(shí)現(xiàn)快速查找凭戴;是動(dòng)態(tài)數(shù)組,相比于數(shù)組容量可實(shí)現(xiàn)動(dòng)態(tài)增長(zhǎng)
- LinkedList底層結(jié)構(gòu)是鏈表炕矮,增刪速度快么夫;是一個(gè)雙向循環(huán)鏈表,也可以被當(dāng)作堆棧肤视、隊(duì)列或雙端隊(duì)列
Q:ArrayList和Vector的區(qū)別档痪?
- 技術(shù)點(diǎn):List對(duì)比
- 參考回答:
- ArrayList非線程安全,建議在單線程中才使用ArrayList邢滑,而在多線程中可以選擇Vector或者CopyOnWriteArrayList腐螟;默認(rèn)初始容量為10,每次擴(kuò)容為原來(lái)的1.5倍
- Vector使用了synchronized關(guān)鍵字困后,是線程安全的遭垛,比ArrayList開(kāi)銷更大,訪問(wèn)更慢操灿;默認(rèn)初始容量為10锯仪,默認(rèn)每次擴(kuò)容為原來(lái)的2倍,可通過(guò)capacityIncrement屬性設(shè)置
Q:HashSet和TreeSet的區(qū)別趾盐?
- 技術(shù)點(diǎn):Set對(duì)比
- 參考回答:
- HashSet不能保證元素的排列順序庶喜;使用Hash算法來(lái)存儲(chǔ)集合中的元素,有良好的存取和查找性能救鲤;通過(guò)
equal()
判斷兩個(gè)元素是否相等久窟,并兩個(gè)元素的hashCode()
返回值也相等- TreeSet是SortedSet接口的實(shí)現(xiàn)類,根據(jù)元素實(shí)際值的大小進(jìn)行排序本缠;采用紅黑樹(shù)的數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)集合元素斥扛;支持兩種排序方法:自然排序(默認(rèn)情況)和定制排序。前者通過(guò)實(shí)現(xiàn)Comparable接口中的
compareTo()
比較兩個(gè)元素之間大小關(guān)系丹锹,然后按升序排列稀颁;后者通過(guò)實(shí)現(xiàn)Comparator接口中的compare()
比較兩個(gè)元素之間大小關(guān)系,實(shí)現(xiàn)定制排列
Q:HashMap和Hashtable的區(qū)別楣黍?
- 技術(shù)點(diǎn):Map對(duì)比
- 參考回答:
- HashMap基于AbstractMap類匾灶,實(shí)現(xiàn)了Map、Cloneable(能被克伦馄)阶女、Serializable(支持序列化)接口颊糜; 非線程安全;允許存在一個(gè)為null的key和任意個(gè)為null的value秃踩;采用鏈表散列的數(shù)據(jù)結(jié)構(gòu)衬鱼,即數(shù)組和鏈表的結(jié)合;初始容量為16憔杨,填充因子默認(rèn)為0.75鸟赫,擴(kuò)容時(shí)是當(dāng)前容量翻倍,即2capacity
- Hashtable基于Map接口和Dictionary類芍秆;線程安全惯疙,開(kāi)銷比HashMap大翠勉,如果多線程訪問(wèn)一個(gè)Map對(duì)象妖啥,使用Hashtable更好;不允許使用null作為key和value对碌;底層基于哈希表結(jié)構(gòu)荆虱;初始容量為11,填充因子默認(rèn)為0.75朽们,擴(kuò)容時(shí)是容量翻倍+1怀读,即2capacity+1
Q:HashMap在put、get元素的過(guò)程骑脱?體現(xiàn)了什么數(shù)據(jù)結(jié)構(gòu)菜枷?
- 技術(shù)點(diǎn):HashMap
- 參考回答:
- 向Hashmap中put元素時(shí),首先判斷key是否為空叁丧,為空則直接調(diào)用putForNullKey()啤誊,不為空則計(jì)算key的hash值得到該元素在數(shù)組中的下標(biāo)值;如果數(shù)組在該位置處沒(méi)有元素拥娄,就直接保存蚊锹;如果有,還要比較是否存在相同的key稚瘾,存在的話就覆蓋原來(lái)key的value牡昆,否則將該元素保存在鏈頭,先保存的在鏈尾摊欠。
- 從Hashmap中g(shù)et元素時(shí)丢烘,計(jì)算key的hash值找到在數(shù)組中的對(duì)應(yīng)的下標(biāo)值,返回該key對(duì)應(yīng)的value即可些椒,如果有沖突就遍歷該位置鏈表尋找key相同的元素并返回對(duì)應(yīng)的value
- 由此可看出HashMap采用鏈表散列的數(shù)據(jù)結(jié)構(gòu)铅协,即數(shù)組和鏈表的結(jié)合,在Java8后又結(jié)合了紅黑樹(shù)摊沉,當(dāng)鏈表元素超過(guò)8個(gè)將鏈表轉(zhuǎn)換為紅黑樹(shù)
Q:如何解決Hash沖突狐史?
- 技術(shù)點(diǎn):Hash沖突
- 參考回答:
- 開(kāi)放定址法:常見(jiàn)的線性探測(cè)方式,在沖突發(fā)生時(shí),順序查看表中下一單元骏全,直到找出一個(gè)空單元或查遍全表
- 鏈地址法:將有沖突數(shù)組位置生出鏈表
- 建立公共溢出區(qū):將哈希表分為基本表和溢出表兩部分苍柏,和基本表發(fā)生沖突的元素一律填入溢出表
- 再哈希法:構(gòu)造多個(gè)不同的哈希函數(shù),有沖突使用下一個(gè)哈希函數(shù)計(jì)算hash值
Q:如何保證HashMap線程安全姜贡?什么原理试吁?
- 技術(shù)點(diǎn):ConcurrentHashMap
- 思路:這里回答一種辦法,使用ConcurrentHashMap
- 參考回答:ConcurrentHashMap是線程安全的HashMap楼咳,它采取鎖分段技術(shù)熄捍,將數(shù)據(jù)分成一段一段的存儲(chǔ),然后給每一段數(shù)據(jù)配一把鎖母怜,當(dāng)一個(gè)線程占用鎖訪問(wèn)其中一個(gè)段數(shù)據(jù)的時(shí)候余耽,其他段的數(shù)據(jù)也能被其他線程訪問(wèn)。在JDK1.8中對(duì)ConcurrentHashmap做了兩個(gè)改進(jìn):
- 取消segments字段苹熏,直接采用
transient volatile HashEntry<K,V>[] table
保存數(shù)據(jù)碟贾,將數(shù)組元素作為鎖,對(duì)每一行數(shù)據(jù)進(jìn)行加鎖轨域,可減少并發(fā)沖突的概率- 數(shù)據(jù)結(jié)構(gòu)由“數(shù)組+單向鏈表”變?yōu)椤皵?shù)組+單向鏈表+紅黑樹(shù)”袱耽,使得查詢的時(shí)間復(fù)雜度可以降低到O(logN),改進(jìn)一定的性能干发。
- 引申:LinkHashMap線程安全的底層實(shí)現(xiàn)
Q:HashMap是有序的嗎朱巨?如何實(shí)現(xiàn)有序?
- 技術(shù)點(diǎn):LinkHashMap
- 思路:這里回答一種辦法枉长,使用LinkedHashMap
- 參考回答:HashMap是無(wú)序的冀续,而LinkedHashMap是有序的HashMap,默認(rèn)為插入順序搀暑,還可以是訪問(wèn)順序沥阳,基本原理是其內(nèi)部通過(guò)Entry維護(hù)了一個(gè)雙向鏈表,負(fù)責(zé)維護(hù)Map的迭代順序
- 引申:LinkHashMap有序的底層實(shí)現(xiàn)
Q:HashMap是如何擴(kuò)容的自点?如何避免擴(kuò)容桐罕?
- 技術(shù)點(diǎn):HashMap
- 參考回答:
- HashMap幾個(gè)默認(rèn)值,初始容量為16桂敛、填充因子默認(rèn)為0.75功炮、擴(kuò)容時(shí)容量翻倍。也就是說(shuō)當(dāng)HashMap中元素個(gè)數(shù)超過(guò)
16*0.75=12
時(shí)會(huì)把數(shù)組的大小擴(kuò)展為2*16=32
术唬,然后重新計(jì)算每個(gè)元素在數(shù)組中的位置- 由于每次擴(kuò)容還需要重新計(jì)算元素Hash值薪伏,損耗性能,所以建議在使用HashMap時(shí)粗仓,最好先估算Map的大小嫁怀,設(shè)置初始值设捐,避免頻繁擴(kuò)容
Q:hashcode()的作用,與equal()有什么區(qū)別塘淑?
- 技術(shù)點(diǎn):Hash值
- 參考回答:hashCode()用于計(jì)算對(duì)象的Hash值萝招,確認(rèn)對(duì)象在散列存儲(chǔ)結(jié)構(gòu)中的存儲(chǔ)地址。和equal()的區(qū)別:
- equals()比較兩個(gè)對(duì)象的地址值是否相等 存捺;hashCode()得到的是對(duì)象的存儲(chǔ)位置槐沼,可能不同對(duì)象會(huì)得到相同值
- 有兩個(gè)對(duì)象,若equals()相等捌治,則hashcode()一定相等岗钩;hashcode()不等,則equals()一定不相等肖油;hashcode()相等兼吓,equals()可能相等、可能不等
- 使用equals()比較兩個(gè)對(duì)象是否相等效率較低构韵,最快辦法是先用hashCode()比較周蹭,如果hashCode()不相等趋艘,則這兩個(gè)對(duì)象肯定不相等疲恢;如果hashCode()相等,此時(shí)再用equal()比較瓷胧,如果equal()也相等显拳,則這兩個(gè)對(duì)象的確相等,反之
- 并發(fā)
Q:同步和非同步搓萧、阻塞和非阻塞的概念
- 技術(shù)點(diǎn):同步杂数、阻塞
- 參考回答:
- 同步和異步體現(xiàn)的是消息的通知機(jī)制:所謂同步,方法A調(diào)用方法B后必須等到方法B返回結(jié)果才能繼續(xù)后面的操作瘸洛;所謂異步揍移,方法A調(diào)用方法B后可讓方法B在調(diào)用結(jié)束后通過(guò)回調(diào)等方式通知方法A
- 阻塞和非阻塞側(cè)重于等待消息時(shí)的狀態(tài):所謂阻塞,就是在結(jié)果返回之前讓當(dāng)前線程掛起反肋;所謂非阻塞那伐,就是在等待時(shí)可做其他事情,通過(guò)輪詢?nèi)ピ儐?wèn)是否已返回結(jié)果
Q:Thread的join()有什么作用石蔗?
- 技術(shù)點(diǎn):線程相關(guān)方法
- 參考回答:Thread的join()的含義是等待該線程終止罕邀,即將掛起調(diào)用線程的執(zhí)行,直到被調(diào)用的對(duì)象完成它的執(zhí)行养距。比如存在兩個(gè)線程t1和t2诉探,下述代碼表示先啟動(dòng)t1,直到t1的任務(wù)結(jié)束棍厌,才輪到t2啟動(dòng)肾胯。
t1.start();
t1.join();
t2.start();
Q:線程的有哪些狀態(tài)竖席?
- 技術(shù)點(diǎn):線程狀態(tài)
- 思路:可分條解釋每種狀態(tài)的特點(diǎn)以及如何轉(zhuǎn)換。詳見(jiàn)要點(diǎn)提煉| 理解JVM之內(nèi)存模型&線程
- 參考回答:在任意一個(gè)時(shí)間點(diǎn),一個(gè)線程只能有且只有其中的一種狀態(tài):
- 新建(New):線程創(chuàng)建后尚未啟動(dòng)
- 運(yùn)行(Runable):包括正在執(zhí)行(Running)和等待著CPU為它分配執(zhí)行時(shí)間(Ready)兩種
- 無(wú)限期等待(Waiting):該線程不會(huì)被分配CPU執(zhí)行時(shí)間哄芜,要等待被其他線程顯式地喚醒柒凉。以下方法會(huì)讓線程陷入無(wú)限期等待狀態(tài):
- 沒(méi)有設(shè)置Timeout參數(shù)的
Object.wait()
- 沒(méi)有設(shè)置Timeout參數(shù)的
Thread.join()
LockSupport.park()
- 限期等待(Timed Waiting):該線程不會(huì)被分配CPU執(zhí)行時(shí)間,但在一定時(shí)間后會(huì)被系統(tǒng)自動(dòng)喚醒东跪。以下方法會(huì)讓線程進(jìn)入限期等待狀態(tài):
Thread.sleep()
- 設(shè)置了Timeout參數(shù)的
Object.wai()
- 設(shè)置了Timeout參數(shù)的
Thread.join()
LockSupport.parkNanos()
LockSupport.parkUntil()
- 阻塞(Blocked):線程被阻塞。和等待狀態(tài)不同的是鹰溜,阻塞狀態(tài)表示在等待獲取到一個(gè)排他鎖虽填,在另外一個(gè)線程放棄這個(gè)鎖的時(shí)候發(fā)生;而等待狀態(tài)表示在等待一段時(shí)間或者喚醒動(dòng)作的發(fā)生曹动,在程序等待進(jìn)入同步區(qū)域的時(shí)候發(fā)生斋日。
- 結(jié)束(Terminated):線程已經(jīng)結(jié)束執(zhí)行
Q:什么是線程安全?保障線程安全有哪些手段墓陈?
- 技術(shù)點(diǎn):線程安全
- 思路:詳見(jiàn)要點(diǎn)提煉| 理解JVM之線程安全&鎖優(yōu)化
- 參考回答:線程安全就是當(dāng)多個(gè)線程訪問(wèn)一個(gè)對(duì)象時(shí)恶守,如果不用考慮這些線程在運(yùn)行時(shí)環(huán)境下的調(diào)度和交替執(zhí)行,也不需要進(jìn)行額外的同步贡必,或者在調(diào)用方進(jìn)行任何其他的協(xié)調(diào)操作兔港,調(diào)用這個(gè)對(duì)象的行為都可以獲得正確的結(jié)果,那這個(gè)對(duì)象是線程安全的仔拟。保證線程安全可從多線程三特性出發(fā):
- 原子性(Atomicity):?jiǎn)蝹€(gè)或多個(gè)操作是要么全部執(zhí)行衫樊,要么都不執(zhí)行
- Lock:保證同時(shí)只有一個(gè)線程能拿到鎖,并執(zhí)行申請(qǐng)鎖和釋放鎖的代碼
- synchronized:對(duì)線程加獨(dú)占鎖利花,被它修飾的類/方法/變量只允許一個(gè)線程訪問(wèn)
- 可見(jiàn)性(Visibility):當(dāng)一個(gè)線程修改了共享變量的值科侈,其他線程能夠立即得知這個(gè)修改
- volatile:保證新值能立即同步到主內(nèi)存,且每次使用前立即從主內(nèi)存刷新炒事;
- synchronized:在釋放鎖之前會(huì)將工作內(nèi)存新值更新到主存中
- 有序性(Ordering):程序代碼按照指令順序執(zhí)行
- volatile: 本身就包含了禁止指令重排序的語(yǔ)義
- synchronized:保證一個(gè)變量在同一個(gè)時(shí)刻只允許一條線程對(duì)其進(jìn)行l(wèi)ock操作臀栈,使得持有同一個(gè)鎖的兩個(gè)同步塊只能串行地進(jìn)入
Q:ReentrantLock和synchronized的區(qū)別?
- 技術(shù)點(diǎn):線程安全(ReentrantLock、synchronized)
- 思路:詳見(jiàn)要點(diǎn)提煉| 理解JVM之線程安全&鎖優(yōu)化
- 參考回答: ReentrantLock與synchronized的不同在于ReentrantLock:
- 等待可中斷:當(dāng)持有鎖的線程長(zhǎng)期不釋放鎖的時(shí)候挠乳,正在等待的線程可以選擇放棄等待权薯,改為處理其他事情。
- 公平鎖:多個(gè)線程在等待同一個(gè)鎖時(shí)欲侮,必須按照申請(qǐng)鎖的時(shí)間順序來(lái)依次獲得鎖崭闲。而synchronized是非公平的,即在鎖被釋放時(shí)威蕉,任何一個(gè)等待鎖的線程都有機(jī)會(huì)獲得鎖刁俭。ReentrantLock默認(rèn)情況下也是非公平的,但可以通過(guò)帶布爾值的構(gòu)造函數(shù)改用公平鎖韧涨。
- 鎖綁定多個(gè)條件:一個(gè)ReentrantLock對(duì)象可以通過(guò)多次調(diào)用newCondition()同時(shí)綁定多個(gè)Condition對(duì)象牍戚。而在synchronized中侮繁,鎖對(duì)象wait()和notify()或notifyAl()只能實(shí)現(xiàn)一個(gè)隱含的條件,若要和多于一個(gè)的條件關(guān)聯(lián)不得不額外地添加一個(gè)鎖如孝。
Q:synchronized和volatile的區(qū)別宪哩?
- 技術(shù)點(diǎn):線程安全(synchronized、volatile)
- 參考回答:
- synchronized能保證操作的原子性第晰,而volatile不可以锁孟,假設(shè)線程A和線程B同時(shí)讀取到變量a值,A修改a后將值更新到主內(nèi)存茁瘦,同時(shí)B也修改a值會(huì)覆蓋A的修改操作
- synchronized可修飾變量品抽、方法和類,而volatile只能修飾變量
- synchronized可能會(huì)造成線程阻塞甜熔,而volatile不會(huì)造成線程的阻塞
Q:synchronized同步代碼塊還有同步方法本質(zhì)上鎖住的是誰(shuí)圆恤?為什么?
- 技術(shù)點(diǎn):線程安全(synchronized)
- 參考回答:本質(zhì)上鎖住的是對(duì)象腔稀。在java虛擬機(jī)中盆昙,每個(gè)對(duì)象和類在邏輯上都和一個(gè)監(jiān)視器相關(guān)聯(lián),synchronized本質(zhì)上是對(duì)一個(gè)對(duì)象監(jiān)視器的獲取焊虏。當(dāng)執(zhí)行同步代碼塊或同步方法時(shí)淡喜,執(zhí)行方法的線程必須先獲得該對(duì)象的監(jiān)視器,才能進(jìn)入同步代碼塊或同步方法炕淮;而沒(méi)有獲取到的線程將會(huì)進(jìn)入阻塞隊(duì)列拆火,直到成功獲取對(duì)象監(jiān)視器的線程執(zhí)行結(jié)束并釋放鎖后跳夭,才會(huì)喚醒阻塞隊(duì)列的線程涂圆,使其重新嘗試對(duì)對(duì)象監(jiān)視器的獲取。
Q:sleep()和wait()的區(qū)別币叹?
- 技術(shù)點(diǎn):sleep()润歉、wait()
- 參考回答:
- sleep()來(lái)自Thread類;wait()來(lái)自O(shè)bject類
- sleep()用于線程控制自身流程颈抚;而wait()用于線程間通信踩衩,配合notify()/notifyAll()在同步代碼塊或同步方法里使用
- sleep()的線程不會(huì)釋放對(duì)象鎖;wait()會(huì)釋放對(duì)象鎖進(jìn)入等待狀態(tài)贩汉,使得其他線程能使用同步代碼塊或同步方法
- Java新動(dòng)態(tài)
Q:是否了解Java1.x的特性嗎驱富?
Q:談?wù)剬?duì)面向過(guò)程編程、面向?qū)ο缶幊踢€有面向切面編程的理解
- 可能意圖:了解候選者對(duì)Java和其他語(yǔ)言的關(guān)注度和看法匹舞、學(xué)習(xí)主動(dòng)性褐鸥、平時(shí)學(xué)習(xí)習(xí)慣
- 思路:Oracle技術(shù)網(wǎng)(Java):https://www.oracle.com/technetwork/cn/java/index.html 、開(kāi)源中國(guó):https://www.oschina.net 赐稽,了解最新動(dòng)態(tài)