2019校招Android面試題解1.0(中篇)
- ofollow,noindex">Animation
Q:Android中有哪幾種類型的動畫?
- 技術點:動畫型別
- 參考回答: 常見三類動畫
- View動畫(View Animation)/補間動畫(Tween animation):對View進行平移、縮放、旋轉和透明度變化的動畫,不能真正的改變view的位置。應用如佈局動畫、Activity切換動畫
- 逐幀動畫(Drawable Animation):是View動畫的一種,它會按照順序播放一組預先定義好的圖片
- 屬性動畫(Property Animation):對該類物件進行動畫操作,真正改變了物件的屬性
Q:幀動畫在使用時需要注意什麼?
- 技術點:幀動畫
- 參考回答:使用禎動畫要注意不能使用尺寸過大的圖片,否則容易造成OOM
Q:View動畫和屬性動畫的區別?
- 技術點:View動畫、屬性動畫
- 參考回答:
Q:View動畫為何不能真正改變View的位置?而屬性動畫為何可以?
- 技術點:View動畫
- 參考回答:View動畫改變的只是View的顯示,而沒有改變View的響應區域;而屬性動畫會通過反射技術來獲取和執行屬性的get、set方法,從而改變了物件位置的屬性值。
Q:屬性動畫插值器和估值器的作用?
- 技術點:屬性動畫
- 參考回答:
- 插值器(Interpolator) :根據 時間流逝的百分比 計算出當前 屬性值改變的百分比 。確定了動畫效果變化的模式,如勻速變化、加速變化等等。View動畫和屬性動畫均可使用。常用的系統內建插值器:
- 線性插值器(LinearInterpolator):勻速動畫
- 加速減速插值器(AccelerateDecelerateInterpolator):動畫兩頭慢中間快
- 減速插值器(DecelerateInterpolator):動畫越來越慢
- 型別估值器(TypeEvaluator) :根據當前 屬性改變的百分比 計算出 改變後的屬性值 。針對於屬性動畫,View動畫不需要型別估值器。常用的系統內建的估值器:
- 整形估值器(IntEvaluator)
- 浮點型估值器(FloatEvaluator)
- Color屬性估值器(ArgbEvaluator)
- 插值器(Interpolator) :根據 時間流逝的百分比 計算出當前 屬性值改變的百分比 。確定了動畫效果變化的模式,如勻速變化、加速變化等等。View動畫和屬性動畫均可使用。常用的系統內建插值器:
Q:Activity、View、Window三者之間的關係?
- 技術點:Activity、View、Window聯絡
- 思路:圍繞Window是Activity和View的橋樑展開
- 參考回答:在Activity啟動過程其中的attach()方法中初始化了PhoneWindow,而PhoneWindow是Window的唯一實現類,然後Activity通過setContentView將View設定到了PhoneWindow上,而View通過WindowManager的addView()、removeView()、updateViewLayout()對View進行管理。
Q:Window有哪幾種類型?
- 技術點:Window型別
- 參考回答:Window有三種類型:
- 應用Window :對應一個Activity。
- 子Window :不能單獨存在,需附屬特定的父Window。如Dialog。
- 系統Window : 需申明許可權才能建立。如Toast。
Q:Activity建立和Dialog建立過程的異同?
- 技術點:Window建立
- 參考回答: Dialog 的Window建立過程:
- 建立WindowDialog。和Activity類似,同樣是通過 PolicyManager.makeNewWindow() 來實現。
- 初始化DecorView並將Dialog的檢視新增到DecorView中去。和Activity類似,同樣是通過 Window.setContentView() 來實現。
- 將DecorView新增到Window中顯示。和Activity一樣,都是在自身要出現在前臺時才會將新增Window。
- Dialog.show() 方法:完成DecorView的顯示。
- WindowManager.remoteViewImmediate() 方法:當Dialog被dismiss時移除DecorView。
Q:談談訊息機制Hander?作用?有哪些要素?流程是怎樣的?
- 技術點:訊息機制
- 參考回答:
- 作用: 跨執行緒通訊 。當子執行緒中進行耗時操作後需要更新UI時,通過Handler將有關UI的操作切換到主執行緒中執行。
- 四要素:
- Message(訊息) :需要被傳遞的訊息,其中包含了訊息ID,訊息處理物件以及處理的資料等,由MessageQueue統一列隊,最終由Handler處理。
- MessageQueue(訊息佇列) :用來存放Handler傳送過來的訊息,內部通過 單鏈表 的資料結構來維護訊息列表,等待Looper的抽取。
- Handler(處理者) :負責Message的傳送及處理。通過 Handler.sendMessage() 向訊息池傳送各種訊息事件;通過 Handler.handleMessage() 處理相應的訊息事件。
- Looper(訊息泵) :通過Looper.loop()不斷地從MessageQueue中抽取Message,按分發機制將訊息分發給目標處理者。
-
具體流程如圖
-
Handler.sendMessage()
傳送訊息時,會通過MessageQueue.enqueueMessage()
向MessageQueue中新增一條訊息; - 通過
Looper.loop()
開啟迴圈後,不斷輪詢呼叫MessageQueue.next()
; - 呼叫目標
Handler.dispatchMessage()
去傳遞訊息,目標Handler收到訊息後呼叫Handler.handlerMessage()
處理訊息。
-
Q:為什麼系統不建議在子執行緒訪問UI?
- 技術點:UI執行緒、子執行緒
- 參考回答:系統不建議在子執行緒訪問UI的原因是,UI控制元件 非執行緒安全 ,在多執行緒中併發訪問可能會導致UI控制元件處於不可預期的狀態。而不對UI控制元件的訪問加上鎖機制的原因有:
- 上鎖會讓UI控制元件變得複雜和低效
- 上鎖後會阻塞某些程序的執行
Q:一個Thread可以有幾個Looper?幾個Handler?
- 技術點:Looper、Handler
- 參考回答:一個Thread只能有一個Looper,可以有多個Handler
- 引申:更多數量關係:Looper有一個MessageQueue,可以處理來自多個Handler的Message;MessageQueue有一組待處理的Message,這些Message可來自不同的Handler;Message中記錄了負責傳送和處理訊息的Handler;Handler中有Looper和MessageQueue;
Q:如何將一個Thread執行緒變成Looper執行緒?Looper執行緒有哪些特點?
- 技術點:Looper
- 參考回答:通過Looper.prepare()可將一個Thread執行緒轉換成Looper執行緒。Looper執行緒和普通Thread不同,它通過MessageQueue來存放訊息和事件、Looper.loop()進行訊息輪詢。
Q:可以在子執行緒直接new一個Handler嗎?那該怎麼做?
- 技術點:Handler
- 參考回答:不同於主執行緒直接new一個Handler,由於子執行緒的Looper需要手動去建立,在建立Handler時需要多一些方法:
new Thread(new Runnable() { @Override public void run() { Looper.prepare();//為子執行緒建立Looper new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); //子執行緒訊息處理 } }; Looper.loop(); //開啟訊息輪詢 } }).start();
Q:Message可以如何建立?哪種效果更好,為什麼?
- 技術點:Message
- 參考回答:建立Message物件的幾種方式:
- Message msg = new Message();
- Message msg = Message.obtain();
- Message msg = handler1.obtainMessage();
後兩種方法都是從整個Messge池中返回一個新的Message例項,能有效避免重複Message建立物件,因此更鼓勵這種方式建立Message
Q:這裡的ThreadLocal有什麼作用?
- 技術點:ThreadLocal
- 參考回答:ThreadLocal類可實現執行緒本地儲存的功能,把共享資料的可見範圍限制在同一個執行緒之內,無須同步就能保證執行緒之間不出現資料爭用的問題,這裡可理解為ThreadLocal幫助Handler找到本執行緒的Looper。
- 底層資料結構:每個執行緒的Thread物件中都有一個ThreadLocalMap物件,它儲存了一組以ThreadLocal.threadLocalHashCode為key、以本地執行緒變數為value的鍵值對,而ThreadLocal物件就是當前執行緒的ThreadLocalMap的訪問入口,也就包含了一個獨一無二的threadLocalHashCode值,通過這個值就可以線上程鍵值值對中找回對應的本地執行緒變數。
Q:主執行緒中Looper的輪詢死迴圈為何沒有阻塞主執行緒?
- 技術點:Looper
- 參考回答:Android是依靠事件驅動的,通過Loop.loop()不斷進行訊息迴圈,可以說Activity的生命週期都是執行在 Looper.loop()的控制之下,一旦退出訊息迴圈,應用也就退出了。而所謂的導致ANR多是因為某個事件在主執行緒中處理時間太耗時,因此只能說是對某個訊息的處理阻塞了Looper.loop(),反之則不然。
Q:使用Hanlder的postDealy()後訊息佇列會發生什麼變化?
- 技術點:Handler
- 參考回答:post delay的Message並不是先等待一定時間再放入到MessageQueue中,而是直接進入並阻塞當前執行緒,然後將其delay的時間和隊頭的進行比較,按照觸發時間進行排序,如果觸發時間更近則放入隊頭,保證隊頭的時間最小、隊尾的時間最大。此時,如果隊頭的Message正是被delay的,則將當前執行緒堵塞一段時間,直到等待足夠時間再喚醒執行該Message,否則喚醒後直接執行。
Q:Android中還了解哪些方便執行緒切換的類?
- 技術點:執行緒通訊
- 參考回答:對Handler進一步的封裝的幾個類:
- 引申:更多是對訊息機制的理解
Q:AsyncTask相比Handler有什麼優點?不足呢?
- 技術點:AsyncTask、Handler
- 參考回答:
- Handler機制存在的 問題 :程式碼相對臃腫;多工同時執行時不易精確控制執行緒。
- 引入AsyncTask的 好處 :建立非同步任務更簡單,直接繼承它可方便實現後臺非同步任務的執行和進度的回撥更新UI,而無需編寫任務執行緒和Handler例項就能完成相同的任務。
Q:使用AsyncTask需要注意什麼?
- 技術點:AsyncTask
- 參考回答:
- 不要直接呼叫onPreExecute()、doInBackground()、onProgressUpdate()、onPostExecute)和onCancelled()方法
- AsyncTask物件必須在 主執行緒 建立
- 引申:談談AsyncTask初始化、五個核心方法如何配合進而體現Handler的作用
Q:AsyncTask中使用的執行緒池大小?
- 技術點:AsyncTask
- 參考回答:在AsyncTask內部實現有兩個執行緒池:
- SerialExecutor :用於任務的排隊,預設是 序列 的執行緒池,其核心執行緒是5、佇列容量是128、最大執行緒數是9
- THREAD_POOL_EXECUTOR :用於真正執行任務。
- 引申:談談對執行緒池的理解
Q:HandlerThread有什麼特點?
- 技術點:HandlerThread
- 參考回答:HandlerThread是一個執行緒類,它繼承自Thread。與普通Thread不同,HandlerThread具有 訊息迴圈 的效果,這是因為它內部
HandlerThread.run()
方法中有Looper,能通過Looper.prepare()
來建立訊息佇列,並通過Looper.loop()
來開啟訊息迴圈。
Q:快速實現子執行緒使用Handler
- 技術點:HandlerThread
- 思路:不同於之前手動在子執行緒建立Looper再構建Handler的想法,這裡從HandlerThread角度去快速實現在子執行緒使用Handler
- 參考回答:HandlerThread實現方法
- 例項化一個HandlerThread物件,引數是該執行緒的名稱;
- 通過 HandlerThread.start()開啟執行緒;
- 例項化一個Handler並傳入HandlerThread中的looper物件,使得與HandlerThread繫結;
- 利用Handler即可執行非同步任務;
- 當不需要HandlerThread時,通過HandlerThread.quit()/quitSafely()方法來終止執行緒的執行。
Q:IntentService的特點?
- 技術點:IntentService
- 思路:和普通執行緒和普通Service比較突出其特點
- 參考回答: 不同於執行緒,IntentService是服務,優先順序比執行緒高,更不容易被系統殺死,因此較適合執行一些 高優先順序 的後臺任務;不同於普通Service,IntentService可 自動建立 子執行緒來執行任務,且任務執行完畢後 自動退出 。
Q:為何不用bindService方式建立IntentService?
- 技術點:IntentService
- 思路:從底層實現出發
- 參考回答:IntentService的工作原理是,在IntentService的onCreate()裡會建立一個HandlerThread,並利用其內部的Looper例項化一個ServiceHandler物件;而這個ServiceHandler用於處理訊息的handleMessage()方法會去呼叫IntentService的onHandleIntent(),這也是為什麼可在該方法中處理後臺任務的邏輯;當有Intent任務請求時會把Intent封裝到Message,然後ServiceHandler會把訊息傳送出,而傳送訊息是在onStartCommand()完成的,只能通過startService()才可走該生命週期方法,因此不能通過bindService建立IntentService。
Q:執行緒池的好處、原理、型別?
- 技術點:執行緒池
- 參考回答:
- (1)執行緒池的好處:
- 重用 執行緒池中的執行緒,避免執行緒的建立和銷燬帶來的效能消耗;
- 有效控制執行緒池的 最大併發數 ,避免大量的執行緒之間因互相搶佔系統資源而導致阻塞現象;
- 進行 執行緒管理 ,提供定時/迴圈間隔執行等功能
- (2)執行緒池的分類:
- FixThreadPool :執行緒數量固定的執行緒池,所有執行緒都是 核心執行緒 ,當執行緒空閒時 不會 被回收;能 快速 響應外界請求。
- CachedThreadPool :執行緒數量不定的執行緒池(最大執行緒數為 Integer.MAX_VALUE ),只有 非核心執行緒 ,空閒執行緒有超時機制,超時回收;適合於執行大量的 耗時較少 的任務
- ScheduledThreadPool :核心執行緒數量 固定 ,非核心執行緒數量 不定 ;可進行 定時 任務和 固定 週期的任務。
- SingleThreadExecutor :只有 一個核心執行緒 ,可確保所有的任務都在同一個執行緒中 按順序 執行;好處是無需處理 執行緒同步 問題。
- (3)執行緒池的原理:實際上通過ThreadPoolExecutor並通過一系列引數來配置各種各樣的執行緒池,具體的引數有:
- corePoolSize 核心執行緒數:一般會線上程中一直存活
- maximumPoolSize 最大執行緒數:當活動執行緒數達到這個數值後,後續的任務將會被阻塞
- keepAliveTime 非核心執行緒超時時間:超過這個時長,閒置的非核心執行緒就會被回收
- unit :用於指定keepAliveTime引數的時間單位
- workQueue 任務佇列:通過執行緒池的
execute()
方法提交的Runnable物件會儲存在這個引數中。 - threadFactory :執行緒工廠,可建立新執行緒
- handler :線上程池無法執行新任務時進行排程
- 引申: 使用Executors各個方法建立執行緒池的弊端
Q:ThreadPoolExecutor的工作策略?
- 技術點:執行緒池
- 參考回答:ThreadPoolExecutor的 預設工作策略 :
- 若程池中的執行緒數量 未達到 核心執行緒數,則會直接啟動一個核心執行緒執行任務。
- 若執行緒池中的執行緒數量 已達到 或者超過核心執行緒數量,則任務會被插入到任務列表等待執行。
- 若任務 無法插入 到任務列表中,往往由於任務列表已滿,此時如果
- 執行緒數量 未達到 執行緒池最大執行緒數,則會啟動一個非核心執行緒執行任務;
- 執行緒數量 已達到 執行緒池規定的最大值,則拒絕執行此任務,ThreadPoolExecutor會呼叫RejectedExecutionHandler的rejectedExecution方法來通知呼叫者。
- 若任務 無法插入 到任務列表中,往往由於任務列表已滿,此時如果
- 引申:ThreadPoolExecutor的拒絕策略
Q:什麼是ANR?什麼情況會出現ANR?如何避免?在不看程式碼的情況下如何快速定位出現ANR問題所在?
- 技術點:ANR
- 思路:
- 參考回答:
- ANR(Application Not Responding,應用無響應):當操作在一段時間內系統無法處理時,會在系統層面會彈出ANR對話方塊
- 產生ANR可能是因為5s內無響應使用者輸入事件、10s內未結束BroadcastReceiver、20s內未結束Service
- 想要避免ANR就不要在主執行緒做耗時操作,而是通過開子執行緒,方法比如繼承Thread或實現Runnable介面、使用AsyncTask、IntentService、HandlerThread等
- 引申:快讀定位ANR方法:使用命令匯出ANR日誌,並分析關鍵資訊,詳見如何分析ANR
Q:載入圖片的時候需要注意什麼?
- 技術點:Bitmap高效載入
- 參考回答:
- 直接載入大容量的高清Bitmap很容易出現顯示不完整、記憶體溢位OOM的問題,所以最好按一定的 取樣率 將圖片縮小後再載入進來
- 為減少流量消耗,可對圖片採用記憶體快取策略,又為了避免圖片佔用過多記憶體導致記憶體溢位,最好以軟引用方式持有圖片
- 如果還需要網上下載圖片,注意要開子執行緒去做下載的耗時操作
Q:LRU演算法的原理?
- 技術點:LRU演算法
- 參考回答:為減少流量消耗,可採用快取策略。常用的快取演算法是LRU(Least Recently Used):
- 引申:感興趣可瞭解具體實現演算法
Q:專案中如何做效能優化的?
- 技術點:效能優化例項
- 思路:舉例說明專案注意了哪些方面的效能優化,如佈局優化、繪製優化、記憶體洩漏優化、 響應速度優化、列表優化、Bitmap優化、 執行緒優化......
Q:瞭解哪些效能優化的工具?
- 技術點:效能優化工具
- 思路:做專案時是否使用過的系統自帶的效能優化工具?公司是否有自己的效能優化工具?實現原理怎樣的?
Q:佈局上如何優化?
- 技術點:佈局優化
- 參考回答:佈局優化的核心就是儘量減少佈局檔案的 層級 ,常見的方式有:
- 多巢狀情況下可使用RelativeLayout減少巢狀。
- 佈局層級相同的情況下使用LinearLayout,它比RelativeLayout更高效。
- 使用
<include>
標籤重用佈局、<merge>
標籤減少層級、<ViewStub>
標籤懶載入。
Q:記憶體洩漏是什麼?為什麼會發生?常見哪些記憶體洩漏的例子?都是怎麼解決的?
- 技術點:記憶體洩漏
- 參考回答:記憶體洩漏(Memory Leak)是指程式在申請記憶體後, 無法釋放 已申請的記憶體空間。簡單地說,發生記憶體洩漏是由於長週期物件持有對短週期物件的引用,使得短週期物件不能被及時回收。常見的幾個例子和解決辦法:
- 單例模式導致的記憶體洩漏:單例傳入引數this來自Activity,使得持有對Activity的引用。
- 解決辦法:傳參context.getApplicationContext()
- Handler導致的記憶體洩漏:Message持有對Handler的引用,而非靜態內部類的Handler又隱式持有對外部類Activity的引用,使得引用關係會保持至訊息得到處理,從而阻止了Activity的回收。
- 解決辦法:使用靜態內部類+WeakReference弱引用;當外部類結束生命週期時清空訊息佇列。
- 執行緒導致的記憶體洩漏:AsyncTask/Runnable以 匿名內部類 的方式存在,會隱式持有對所在Activity的引用。
- 解決辦法:將AsyncTask和Runnable設為靜態內部類或獨立出來;線上程內部採用弱引用儲存Context引用
- 資源未關閉導致的記憶體洩漏:未及時登出資源導致記憶體洩漏,如BraodcastReceiver、File、Cursor、Stream、Bitmap等。
- 解決辦法:在Activity銷燬的時候要及時關閉或者登出。
- BraodcastReceiver:呼叫
unregisterReceiver()
登出; - Cursor,Stream、File:呼叫
close()
關閉; - 動畫:在
Activity.onDestroy()
中呼叫Animator.cancel()
停止動畫
- BraodcastReceiver:呼叫
- 解決辦法:在Activity銷燬的時候要及時關閉或者登出。
- 單例模式導致的記憶體洩漏:單例傳入引數this來自Activity,使得持有對Activity的引用。
- 引申:談談專案中是如何注意記憶體洩漏的問題
Q:記憶體洩漏和記憶體溢位的區別
- 技術點:記憶體洩漏、記憶體溢位
- 參考回答:
- 記憶體洩漏(Memory Leak)是指程式在申請記憶體後, 無法釋放 已申請的記憶體空間。是造成應用程式OOM的主要原因之一。
- 記憶體溢位(out of memory)是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用。
Q:什麼情況會導致記憶體溢位?
- 技術點:記憶體溢位
- 參考回答:記憶體洩漏是導致記憶體溢位的主要原因;直接載入大圖片也易造成記憶體溢位
- 引申:談談如何避免記憶體溢位(如何避免記憶體洩漏、避免直接載入大圖片)
-
開源框架(略)
-
谷歌新動態
Q:是否瞭解和使用過谷歌推出的新技術?
Q:有了解剛釋出的Androidx.0的特性嗎?
Q:Kotlin對Java做了哪些優化?
- 可能意圖:瞭解候選者對谷歌&安卓的關注度、共同探討對新技術的看法、學習主動性、平時學習習慣
- 思路:谷歌的安卓官方網站(中文版): https://developer.android.google.cn ,瞭解最新動態
1.2 Java
- 基礎
Q:面向物件程式設計的四大特性及其含義?
- 技術點:面向物件程式設計特點
- 思路:分條簡述每個特性的含義
- 參考回答:
- 抽象:對現實世界的事物進行概括,抽象為在計算機虛擬世界中有意義的實體
- 封裝:將某事物的屬性和行為包裝到物件中,構成一個不可分割的獨立實體,資料被保護在抽象資料型別的內部,並且儘可能地隱藏內部的細節,只保留一些對外介面使之與外部發生聯絡
- 繼承:子類繼承父類,不僅可以有父類原有的方法和屬性,也可以增加自己的或者重寫父類的方法及屬性
- 多型:允許不同類的物件對同一訊息做出各自的響應
Q:String、StringBuffer和StringBuilder的區別?
- 技術點:String
- 參考回答:
- String是字串常量,而StringBuffer、StringBuilder都是字串變數,即String物件一建立後不可更改,而後兩者的物件是可更改的:
- StringBuffer是執行緒安全的,而StringBuilder是非執行緒安全的,這是由於StringBuffer對方法加了同步鎖或者對呼叫的方法加了同步鎖
- String更適用於少量的字串操作的情況,StringBuilder適用於單執行緒下在字元緩衝區進行大量操作的情況,StringBuffer適用於多執行緒下在字元緩衝區進行大量操作的情況
Q:String a=""和String a=new String("")的的關係和異同?
- 技術點:String
- 參考回答:
- 通過String a=""直接賦值的方式得到的是一個字串常量,存在於常量池;注意,相同內容的字串在常量池中只有一個,即如果池已包含內容相等的字串會返回池中的字串,反之會將該字串放入池中
- 通過new String("")建立的字串不是常量是例項物件,會在堆記憶體開闢空間並存放資料,且每個例項物件都有自己的地址空間
- 引申:對於用String a=""和String a=new String("")兩種方式定義的字串,判斷使用equals()、"=="比較結果是什麼
Q:Object的equal()和==的區別?
- 技術點:equal()、==
- 參考回答:
- equals():是Object的公有方法,具體含義取決於如何重寫,比如String的equals()比較的是兩個字串的內容是否相同
- "==" :對於基本資料型別來說,比較的是兩個變數值是夠是否相等,對於引用型別來說,比較的是兩個物件的記憶體地址是否相同
- 引申:對於用String a=""和String a=new String("")兩種方式定義的字串,判斷使用equals()、"=="比較結果是什麼
Q:裝箱、拆箱什麼含義?
- 技術點:裝箱、拆箱
- 參考回答:裝箱就是自動將基本資料型別轉換為包裝器型別,拆箱就是自動將包裝器型別轉換為基本資料型別
Q:int和Integer的區別?
- 技術點:基本資料型別、引用型別
- 參考回答:
- Integer是int的包裝類,int則是java的一種基本資料型別
- Integer變數必須例項化後才能使用,而int變數不需要
- Integer實際是物件的引用,當new一個Integer時,實際上是生成一個指標指向此物件;而int則是直接儲存資料值
- Integer的預設值是null,int的預設值是0
Q:遇見過哪些執行時異常?異常處理機制知道哪些?
- 技術點:Java異常機制
- 思路:對Throwable異常進行分類說明每種異常的特點和常見問題,簡述幾種常見異常處理機制,詳見Java基礎之異常機制
- 參考回答:
- (1) Throwable繼承層次結構,可見分成兩大類Error和Exception:
- Error(錯誤):指程式 無法 恢復的異常情況,表示執行應用程式中較嚴重的問題;發生於虛擬機器自身、或者在虛擬機器試圖執行應用時,如Virtual MachineError(Java虛擬機器執行錯誤)、NoClassDefFoundError(類定義錯誤);屬於 不可查 異常,即不強制程式設計師必須處理,即使不處理也不會出現語法錯誤。
- Exception(異常):指程式 有可能 恢復的異常情況,表示程式本身可以處理的異常。又分兩大類:
- RuntimeException(執行時異常):由程式 自身 的問題導致產生的異常;如NullPointerException(空指標異常)、IndexOutOfBoundsException(下標越界異常);屬於 不可查 異常。
- 非執行時異常:由程式 外部 的問題引起的異常;除了RuntimeException以外的異常,如FileNotFoundException(檔案不存在異常);屬於 可查 異常,即強制程式設計師必須進行處理,如果不進行處理則會出現語法錯誤。
- (2)常見的異常處理機制有:
- 捕捉異常:由系統自動丟擲異常,即try捕獲異常->catch處理異常->finally 最終處理
- 丟擲異常:在方法中將異常物件 顯性 地丟擲,之後異常會沿著呼叫層次向上丟擲,交由呼叫它的方法來處理。配合throws宣告丟擲的異常和throw丟擲異常
- 自定義異常:繼承Execption類或其子類
Q:什麼是反射,有什麼作用和應用?
- 技術點:反射
- 思路:簡述反射的定義、功能和應用,詳見Java基礎之泛型&反射
- 參考回答:
- 含義 :在執行狀態中,對於任意一個類都能知道它的所有屬性和方法,對於任何一個物件都能夠呼叫它的任何一個方法和屬性。
- 功能 :動態性,體現在:在執行時判斷任意一個類所具有的屬性和方法; 在執行時判斷任意一個物件所屬的類;在執行時構造任意一個類的物件;在執行時呼叫任意一個物件的方法;生成動態代理
- 應用:反射&泛型
- 引申:是否在專案中使用過反射機制,有什麼優缺點
Q:什麼是內部類?有什麼作用?靜態內部類和非靜態內部類的區別?
- 技術點:內部類
- 思路:
- 參考回答:內部類就是定義在另外一個類裡面的類。它隱藏在外部類中,封裝性更強,不允許除外部類外的其他類訪問它;但它可直接訪問外部類的成員。靜態內部類和非靜態內部類的區別有:
- 靜態內部類是指被宣告為static的內部類,可不依賴外部類例項化;而非靜態內部類需要通過生成外部類來間接生成。
- 靜態內部類只能訪問外部類的靜態成員變數和靜態方法,而非靜態內部類由於持有對外部類的引用,可以訪問外部類的所用成員
- 引申:談談匿名內部類
Q:final、finally、finalize()分別表示什麼含義
- 技術點:final、finally、finalize()
- 參考回答:
- final關鍵字表示不可更改,具體體現在:
- final修飾的變數必須要初始化,且賦初值後不能再重新賦值
- final修飾的方法不能被子類重寫
- final修飾的類不能被繼承
- finally:和try、catch成套使用進行異常處理,無論是否捕獲或處理異常,finally塊裡的語句都會被執行,在以下4種特殊情況下,finally塊才不會被執行:
System.exit()
- finalize():是Object中的方法,當垃圾回收器將回收物件從記憶體中清除出去之前會呼叫finalize(),但此時並不代表該回收物件一定會“死亡”,還有機會“逃脫”
- final關鍵字表示不可更改,具體體現在:
Q:重寫和過載的區別?
- 技術點:重寫、過載
- 參考回答:重寫表示子類重寫父類的方法;過載表示有多個同名函式同時存在,區別在於有不同的引數個數或型別
- 引申:談談動態分派和靜態分派
Q:抽象類和介面的異同?
- 技術點:抽象類、介面
- 參考回答:
- 使用上的區別:一個類只能繼承一個抽象類卻可以實現多個介面
- 設計上的區別:介面是對行為的抽象,無需有子類的前提,是自上而下的設計理念;抽象類是對類的抽象,建立於相似子類之上,是自下而上的設計理念
Q:為什麼匿名內部類中使用區域性變數要用final修飾?
- 技術點:匿名內部類
- 參考回答:一方面,由於方法中的區域性變數的生命週期很短,一旦方法結束變數就要被銷燬,為了保證在內部類中能找到外部區域性變數,通過final關鍵字可得到一個外部變數的引用;另一方面,通過final關鍵字也不會在內部類去做修改該變數的值,保護了資料的一致性。
Q:Object有哪些公有方法?
- 技術點:Object
- 思路:列舉常見的幾個公有方法
- 參考回答:
- equals(): 和==作用相似
- hashCode():用於雜湊查詢,重寫了equals()一般都要重寫該方法
- getClass(): 獲取Class物件
- wait():讓當前執行緒進入等待狀態,並釋放它所持有的鎖
- notify()¬ifyAll(): 喚醒一個(所有)正處於等待狀態的執行緒
- toString():轉換成字串
- 引申:equals()和==的不同、在synchronized 同步程式碼塊裡wait()和notify()¬ifyAll()如何配合、hashCode()和equals()的關係、獲取Class物件還有什麼方法
Q:Java集合框架中有哪些類?都有什麼特點
- 技術點:集合框架
- 思路:分條解釋每種類的特點
- 參考回答:可將Java集合框架大致可分為Set、List、Queue 和Map四種體系
- Set:代表 無序、不可重複 的集合,常見的類如HashSet、TreeSet
- List:代表 有序、可重複 的集合,常見的類如動態陣列ArrayList、雙向連結串列LinkedList、可變陣列Vector
- Map:代表具有 對映關係 的集合,常見的類如HashMap、LinkedHashMap、TreeMap
- Queue:代表一種 佇列 集合
Q:集合、陣列、泛型的關係,並比較
- 技術點:集合、陣列、泛型
- 參考回答:
- (1)集合和陣列的區別:
- 陣列元素可以是基本型別,也可以是物件;陣列長度限定;陣列只能儲存一種型別的資料元素
- 集合元素只能是物件;集合長度可變;集合可儲存不同種的資料元素
- (2)泛型相比與集合的好處在於它 安全簡單 。具體體現在提供編譯時的強型別檢查,而不用等到執行;可避免類型別強制轉換
Q:ArrayList和LinkList的區別?
- 技術點:List對比
- 參考回答:
- ArrayList 的底層結構是 陣列 ,可用索引實現快速查詢;是動態陣列,相比於陣列容量可實現動態增長
- LinkedList 底層結構是 連結串列 ,增刪速度快;是一個 雙向迴圈 連結串列,也可以被當作堆疊、佇列或雙端佇列
Q:ArrayList和Vector的區別?
- 技術點:List對比
- 參考回答:
- ArrayList 非執行緒安全,建議在單執行緒中才使用ArrayList,而在多執行緒中可以選擇Vector或者CopyOnWriteArrayList;預設初始容量為10,每次擴容為原來的1.5倍
- Vector 使用了synchronized關鍵字,是 執行緒安全 的,比ArrayList開銷更大,訪問更慢;預設初始容量為10,預設每次擴容為原來的2倍,可通過 capacityIncrement 屬性設定
Q:HashSet和TreeSet的區別?
- 技術點:Set對比
- 參考回答:
- HashSet 不能保證元素的排列順序;使用 Hash演算法 來儲存集合中的元素,有良好的存取和查詢效能;通過
equal()
判斷兩個元素是否相等,並兩個元素的hashCode()
返回值也相等 - TreeSet 是SortedSet介面的實現類,根據元素 實際值的大小 進行排序;採用 紅黑樹 的資料結構來儲存集合元素;支援兩種排序方法: 自然排序 (預設情況)和 定製排序 。前者通過實現 Comparable介面 中的
compareTo()
比較兩個元素之間大小關係,然後按升序排列;後者通過實現 Comparator介面 中的compare()
比較兩個元素之間大小關係,實現定製排列
- HashSet 不能保證元素的排列順序;使用 Hash演算法 來儲存集合中的元素,有良好的存取和查詢效能;通過
Q:HashMap和Hashtable的區別?
- 技術點:Map對比
- 參考回答:
- HashMap 基於AbstractMap類,實現了Map、 Cloneable (能被克隆)、 Serializable (支援序列化)介面; 非執行緒安全 ;允許存在一個為null的key和任意個為null的value;採用 連結串列雜湊 的資料結構,即陣列和連結串列的結合;初始容量為16,填充因子預設為0.75,擴容時是當前容量翻倍,即2capacity
- Hashtable 基於Map介面和Dictionary類; 執行緒安全 ,開銷比HashMap大,如果多執行緒訪問一個Map物件,使用Hashtable更好;不允許使用null作為key和value;底層基於雜湊表結構;初始容量為11,填充因子預設為0.75,擴容時是容量翻倍+1,即2capacity+1
Q:HashMap在put、get元素的過程?體現了什麼資料結構?
- 技術點:HashMap
- 參考回答:
- 向Hashmap中put元素時,首先判斷key是否為空,為空則直接呼叫putForNullKey(),不為空則計算key的hash值得到該元素在陣列中的下標值;如果陣列在該位置處沒有元素,就直接儲存;如果有,還要比較是否存在相同的key,存在的話就覆蓋原來key的value,否則將該元素儲存在鏈頭,先儲存的在鏈尾。
- 從Hashmap中get元素時,計算key的hash值找到在陣列中的對應的下標值,返回該key對應的value即可,如果有衝突就遍歷該位置連結串列尋找key相同的元素並返回對應的value
- 由此可看出HashMap採用 連結串列雜湊 的資料結構,即陣列和連結串列的結合,在Java8後又結合了紅黑樹,當連結串列元素超過8個將連結串列轉換為紅黑樹
Q:如何解決Hash衝突?
- 技術點:Hash衝突
- 參考回答:
- 開放定址法:常見的線性探測方式,在衝突發生時,順序查看錶中下一單元,直到找出一個空單元或查遍全表
- 鏈地址法:將有衝突陣列位置生出連結串列
- 建立公共溢位區:將雜湊表分為基本表和溢位表兩部分,和基本表發生衝突的元素一律填入溢位表
- 再雜湊法:構造多個不同的雜湊函式,有衝突使用下一個雜湊函式計算hash值
Q:如何保證HashMap執行緒安全?什麼原理?
- 技術點:ConcurrentHashMap
- 思路:這裡回答一種辦法,使用ConcurrentHashMap
- 參考回答:ConcurrentHashMap是執行緒安全的HashMap,它採取鎖分段技術,將資料分成一段一段的儲存,然後給每一段資料配一把鎖,當一個執行緒佔用鎖訪問其中一個段資料的時候,其他段的資料也能被其他執行緒訪問。在JDK1.8中對ConcurrentHashmap做了兩個改進:
transient volatile HashEntry<K,V>[] table
- 引申:LinkHashMap執行緒安全的底層實現
Q:HashMap是有序的嗎?如何實現有序?
- 技術點:LinkHashMap
- 思路:這裡回答一種辦法,使用LinkedHashMap
- 參考回答:HashMap是無序的,而LinkedHashMap是有序的HashMap,預設為插入順序,還可以是訪問順序,基本原理是其內部通過Entry維護了一個雙向連結串列,負責維護Map的迭代順序
- 引申:LinkHashMap有序的底層實現
Q:HashMap是如何擴容的?如何避免擴容?
- 技術點:HashMap
- 參考回答:
- HashMap幾個預設值,初始容量為16、填充因子預設為0.75、擴容時容量翻倍。也就是說當HashMap中元素個數超過
16*0.75=12
時會把陣列的大小擴充套件為2*16=32
,然後重新計算每個元素在陣列中的位置 - 由於每次擴容還需要重新計算元素Hash值,損耗效能,所以建議在使用HashMap時,最好先估算Map的大小,設定初始值,避免頻繁擴容
- HashMap幾個預設值,初始容量為16、填充因子預設為0.75、擴容時容量翻倍。也就是說當HashMap中元素個數超過
Q:hashcode()的作用,與equal()有什麼區別?
- 技術點:Hash值
- 參考回答:hashCode()用於計算物件的Hash值,確認物件在雜湊儲存結構中的儲存地址。和equal()的區別:
- equals()比較兩個物件的地址值是否相等 ;hashCode()得到的是物件的儲存位置,可能不同物件會得到相同值
- 有兩個物件,若equals()相等,則hashcode()一定相等;hashcode()不等,則equals()一定不相等;hashcode()相等,equals()可能相等、可能不等
- 使用equals()比較兩個物件是否相等效率較低,最快辦法是先用hashCode()比較,如果hashCode()不相等,則這兩個物件肯定不相等;如果hashCode()相等,此時再用equal()比較,如果equal()也相等,則這兩個物件的確相等,反之
- 併發
Q:同步和非同步、阻塞和非阻塞的概念
- 技術點:同步、阻塞
- 參考回答:
- 同步和非同步體現的是訊息的通知機制:所謂同步,方法A呼叫方法B後必須等到方法B返回結果才能繼續後面的操作;所謂非同步,方法A呼叫方法B後可讓方法B在呼叫結束後通過回撥等方式通知方法A
- 阻塞和非阻塞側重於等待訊息時的狀態:所謂阻塞,就是在結果返回之前讓當前執行緒掛起;所謂非阻塞,就是在等待時可做其他事情,通過輪詢去詢問是否已返回結果
Q:Thread的join()有什麼作用?
- 技術點:執行緒相關方法
- 參考回答:Thread的join()的含義是等待該執行緒終止,即將掛起呼叫執行緒的執行,直到被呼叫的物件完成它的執行。比如存在兩個執行緒t1和t2,下述程式碼表示先啟動t1,直到t1的任務結束,才輪到t2啟動。
t1.start(); t1.join(); t2.start();
Q:執行緒的有哪些狀態?
- 技術點:執行緒狀態
- 思路:可分條解釋每種狀態的特點以及如何轉換。詳見 要點提煉| 理解JVM之記憶體模型&執行緒
- 參考回答:在任意一個時間點,一個執行緒只能有且只有其中的一種狀態:
- 新建 (New):執行緒建立後尚未啟動
- 執行 (Runable):包括正在執行(Running)和等待著CPU為它分配執行時間(Ready)兩種
- 無限期等待 (Waiting):該執行緒不會被分配CPU執行時間,要等待被其他執行緒顯式地喚醒。以下方法會讓執行緒陷入無限期等待狀態:
Object.wait() Thread.join() LockSupport.park()
- 限期等待 (Timed Waiting):該執行緒不會被分配CPU執行時間,但在一定時間後會被系統自動喚醒。以下方法會讓執行緒進入限期等待狀態:
Thread.sleep() Object.wai() Thread.join() LockSupport.parkNanos() LockSupport.parkUntil()
- 阻塞 (Blocked):執行緒被阻塞。和等待狀態不同的是,阻塞狀態表示在等待獲取到一個 排他鎖 ,在另外一個執行緒放棄這個鎖的時候發生;而等待狀態表示在等待一段 時間 或者 喚醒動作 的發生,在程式等待進入同步區域的時候發生。
- 結束 (Terminated):執行緒已經結束執行
Q:什麼是執行緒安全?保障執行緒安全有哪些手段?
- 技術點:執行緒安全
- 思路:詳見 要點提煉| 理解JVM之執行緒安全&鎖優化
- 參考回答:執行緒安全就是當多個執行緒訪問一個物件時,如果不用考慮這些執行緒在執行時環境下的排程和交替執行,也不需要進行額外的同步,或者在呼叫方進行任何其他的協調操作,呼叫這個物件的行為都可以獲得正確的結果,那這個物件是執行緒安全的。保證執行緒安全可從多執行緒三特性出發:
- 原子性 (Atomicity):單個或多個操作是要麼全部執行,要麼都不執行
- Lock:保證同時只有一個執行緒能拿到鎖,並執行申請鎖和釋放鎖的程式碼
- synchronized:對執行緒加獨佔鎖,被它修飾的類/方法/變數只允許一個執行緒訪問
- 可見性 (Visibility):當一個執行緒修改了共享變數的值,其他執行緒能夠立即得知這個修改
- volatile:保證新值能 立即 同步到主記憶體,且每次使用前立即從主記憶體重新整理;
- synchronized:在釋放鎖之前會將工作記憶體新值更新到主存中
- 有序性 (Ordering):程式程式碼按照指令順序執行
- volatile: 本身就包含了禁止指令重排序的語義
- synchronized:保證一個變數在同一個時刻只允許一條執行緒對其進行lock操作,使得持有同一個鎖的兩個同步塊只能序列地進入
- 原子性 (Atomicity):單個或多個操作是要麼全部執行,要麼都不執行
Q:ReentrantLock和synchronized的區別?
- 技術點:執行緒安全(ReentrantLock、synchronized)
- 思路:詳見 要點提煉| 理解JVM之執行緒安全&鎖優化
- 參考回答: ReentrantLock與synchronized的 不同 在於ReentrantLock:
- 等待可中斷 :當持有鎖的執行緒長期不釋放鎖的時候,正在等待的執行緒可以選擇放棄等待,改為處理其他事情。
- 公平鎖 :多個執行緒在等待同一個鎖時,必須按照申請鎖的時間順序來依次獲得鎖。而synchronized是非公平的,即在鎖被釋放時,任何一個等待鎖的執行緒都有機會獲得鎖。ReentrantLock預設情況下也是非公平的,但可以通過帶布林值的建構函式改用公平鎖。
- 鎖繫結多個條件 :一個ReentrantLock物件可以通過多次呼叫newCondition()同時繫結多個Condition物件。而在synchronized中,鎖物件wait()和notify()或notifyAl()只能實現一個隱含的條件,若要和多於一個的條件關聯不得不額外地新增一個鎖。
Q:synchronized和volatile的區別?
- 技術點:執行緒安全(synchronized、volatile)
- 參考回答:
- synchronized能保證操作的原子性,而volatile不可以,假設執行緒A和執行緒B同時讀取到變數a值,A修改a後將值更新到主記憶體,同時B也修改a值會覆蓋A的修改操作
- synchronized可修飾變數、方法和類,而volatile只能修飾變數
- synchronized可能會造成執行緒阻塞,而volatile不會造成執行緒的阻塞
Q:synchronized同步程式碼塊還有同步方法本質上鎖住的是誰?為什麼?
- 技術點:執行緒安全(synchronized)
- 參考回答:本質上鎖住的是物件。在java虛擬機器中,每個物件和類在邏輯上都和一個監視器相關聯,synchronized本質上是對一個物件監視器的獲取。當執行同步程式碼塊或同步方法時,執行方法的執行緒必須先獲得該物件的監視器,才能進入同步程式碼塊或同步方法;而沒有獲取到的執行緒將會進入阻塞佇列,直到成功獲取物件監視器的執行緒執行結束並釋放鎖後,才會喚醒阻塞佇列的執行緒,使其重新嘗試對物件監視器的獲取。
Q:sleep()和wait()的區別?
- 技術點:sleep()、wait()
- 參考回答:
- sleep()來自Thread類;wait()來自Object類
- sleep()用於執行緒控制自身流程;而wait()用於執行緒間通訊,配合notify()/notifyAll()在同步程式碼塊或同步方法裡使用
- sleep()的執行緒不會釋放物件鎖;wait()會釋放物件鎖進入等待狀態,使得其他執行緒能使用同步程式碼塊或同步方法
- Java新動態
Q:是否瞭解Java1.x的特性嗎?
Q:談談對面向過程程式設計、面向物件程式設計還有面向切面程式設計的理解
- 可能意圖:瞭解候選者對Java和其他語言的關注度和看法、學習主動性、平時學習習慣
- 思路:Oracle技術網(Java): https://www.oracle.com/technetwork/cn/java/index.html 、開源中國: https://www.oschina.net ,瞭解最新動態