LinkedHashMap 的應用java
基於 LinkedHashMap 的訪問順序的特色,可構造一個 LRU(Least Recently Used) 最近最少使用簡單緩存。 也有一些開源的緩存產品如 ehcache 的淘汰策略( LRU )就是在 LinkedHashMap 上擴展的。程序員
Cloneable 接口實現原理面試
Cloneable接口是Java開發中經常使用的一個接口, 它的做用是使一個類的實例可以將自身拷貝到另外一個新的實例中, 注意,這裏所說的「拷貝」拷的是對象實例,而不是類的定義,進一步說,拷貝的是一個類的實例中各字段的值。數組
在開發過程當中,拷貝實例是常見的一種操做,若是一個類中的字段較多,而咱們又採用在客戶端中逐字段複製的方 法進行拷貝操做的話,將不可避免的形成客戶端代碼繁雜冗長,並且也沒法對類中的私有成員進行復制,而若是讓須要 具有拷貝功能的類實現Cloneable接口,並重寫clone()方法,就能夠經過調用clone()方法的方式簡潔地實現實例 拷貝功能
深拷貝(深複製)和淺拷貝(淺複製)是兩個比較通用的概念,尤爲在C++語言中,若不弄懂,則會在delete的時候出問題,可是咱們在這幸虧用的是Java。雖然Java自動管理對象的回收,但對於深拷貝(深複製)和淺拷貝(淺複製),咱們 仍是要給予足夠的重視,由於有時這兩個概念每每會給咱們帶來不小的困惑。緩存
淺拷貝是指拷貝對象時僅僅拷貝對象自己(包括對象中的基本變量),而不拷貝對象包含的引用指向的對象。深拷 貝不只拷貝對象自己,並且拷貝對象包含的引用指向的全部對象。舉例來講更加清楚:對象 A1 中包含對 B1 的引用, B1 中包含對 C1 的引用。淺拷貝 A1 獲得 A2 , A2 中依然包含對 B1 的引用, B1 中依然包含對 C1 的引 用。深拷貝則是對淺拷貝的遞歸,深拷貝 A1 獲得 A2 , A2 中包含對 B2 ( B1 的 copy )的引用, B2 中包含 對 C2 ( C1 的 copy )的引用。性能優化
若不對clone()方法進行改寫,則調用此方法獲得的對象即爲淺拷貝架構
異常分類以及處理機制併發
Java標準庫內建了一些通用的異常,這些類以Throwable爲頂層父類。分佈式
Throwable又派生出Error類和Exception類。微服務
錯誤:Error類以及他的子類的實例,表明了JVM自己的錯誤。錯誤不能被程序員經過代碼處理,Error不多出現。
所以,程序員應該關注Exception爲父類的分支下的各類異常類。
異常:Exception以及他的子類,表明程序運行時發送的各類不指望發生的事件。能夠被Java異常處理機制使用, 是異常處理的核心。
整體上咱們根據 Javac 對異常的處理要求,將異常類分爲二類。
非檢查異常( unckecked exception ): Error 和 RuntimeException 以及他們的子類。 javac 在編譯時, 不會提示和發現這樣的異常,不要求在程序處理這些異常。因此若是願意,咱們能夠編寫代碼處理(使用 try… catch…finally )這樣的異常,也能夠不處理。對於這些異常,咱們應該修正代碼,而不是去經過異常處理器處理 。這樣的異常發生的緣由多半是代碼寫的有問題。如除0錯誤 ArithmeticException ,錯誤的強制類型轉換錯 誤 ClassCastException ,數組索引越界 ArrayIndexOutOfBoundsException ,使用了空對象 NullPointerException 等等。
檢查異常( checked exception ):除了 Error 和 RuntimeException 的其它異常。 javac 強制要求程序員 爲這樣的異常作預備處理工做(使用 try…catch…finally 或者 throws )。在方法中要麼用 try-catch 語句捕 獲它並處理,要麼用throws子句聲明拋出它,不然編譯不會經過。這樣的異常通常是由程序的運行環境致使的。因 爲程序可能被運行在各類未知的環境下,而程序員沒法干預用戶如何使用他編寫的程序,因而程序員就應該爲這樣 的異常時刻準備着。如 SQLException , IOException , ClassNotFoundException 等。
須要明確的是:檢查和非檢查是對於 javac 來講的,這樣就很好理解和區分了。
wait 和 sleep 的區別
源碼以下
一、 sleep 來自 Thread 類,和 wait 來自 Object 類。 二、最主要是sleep方法沒有釋放鎖,而wait方法釋放了 鎖,使得其餘線程可使用同步控制塊或者方法。 三、wait,notify和 notifyAll 只能在同步控制方法或者同步控制塊裏面使用,而 sleep 能夠在任何地方使用(使 用範圍)
四、 sleep 必須捕獲異常,而 wait , notify 和 notifyAll 不須要捕獲異常
(1) sleep 方法屬於 Thread 類中方法,表示讓一個線程進入睡眠狀態,等待必定的時間以後,自動醒來進入到可 運行狀態,不會立刻進入運行狀態,由於線程調度機制恢復線程的運行也須要時間,一個線程對象調用了 sleep 方法以後,並不會釋放他所持有的全部對象鎖,因此也就不會影響其餘進程對象的運行。但在 sleep 的過程當中過 程中有可能被其餘對象調用它的 interrupt() ,產生 InterruptedException 異常,若是你的程序不捕獲這個異 常,線程就會異常終止,進入 TERMINATED 狀態,若是你的程序捕獲了這個異常,那麼程序就會繼續執行catch語 句塊(可能還有 finally 語句塊)以及之後的代碼。
注意 sleep() 方法是一個靜態方法,也就是說他只對當前對象有效,經過 t.sleep() 讓t對象進入 sleep ,這樣 的作法是錯誤的,它只會是使當前線程被 sleep 而不是 t 線程
(2) wait 屬於 Object 的成員方法,一旦一個對象調用了wait方法,必需要採用 notify() 和 notifyAll() 方法 喚醒該進程;若是線程擁有某個或某些對象的同步鎖,那麼在調用了 wait() 後,這個線程就會釋放它持有的全部 同步資源,而不限於這個被調用了 wait() 方法的對象。 wait() 方法也一樣會在 wait 的過程當中有可能被其餘對 象調用 interrupt() 方法而產生 。
數組在內存中如何分配
對於 Java 數組的初始化,有如下兩種方式,這也是面試中常常考到的經典題目:
靜態初始化:初始化時由程序員顯式指定每一個數組元素的初始值,由系統決定數組長度,如:
動態初始化:初始化時由程序員顯示的指定數組的長度,由系統爲數據每一個元素分配初始值,如:
由於 Java 數組變量是引用類型的變量,因此上述幾行初始化語句執行後,三個數組在內存中的分配狀況以下圖所 示:
由上圖可知,靜態初始化方式,程序員雖然沒有指定數組長度,可是系統已經自動幫咱們給分配了,而動態初始化 方式,程序員雖然沒有顯示的指定初始化值,可是由於 Java 數組是引用類型的變量,因此係統也爲每一個元素分配 了初始化值 null ,固然不一樣類型的初始化值也是不同的,假設是基本類型int類型,那麼爲系統分配的初始化值 也是對應的默認值0。
關注做者,我會不按期在思否分享Java,Spring,MyBatis,Redis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化、分佈式架構,BATJ面試 等資料…