出自[最近5年133個Java面試問題列表](http://www.importnew.com/17232.html)
Java 面試隨著時間的改變而改變。在過去的日子里,當你知道 String 和 StringBuilder 的區別就能讓你直接進入第二輪面試,但是現在問題變得越來越高級,面試官問的問題也更深入。 在我初入職場的時候,類似于 Vector 與 Array 的區別、HashMap 與 Hashtable 的區別是最流行的問題,只需要記住它們,就能在面試中獲得更好的機會,但這種情形已經不復存在。如今,你將會被問到許多 Java 程序員都沒有看過的領域,如 NIO,[設計模式](http://www.amazon.cn/gp/product/B001130JN8/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=importnew-23&linkCode=as2&camp=536&creative=3200&creativeASIN=B001130JN8 "設計模式:可復用面向對象軟件的基礎"),成熟的單元測試,或者那些很難掌握的知識,如并發、算法、數據結構及編碼。
由于我喜歡研究面試題,因此我已經收集了許多的面試問題,包括許多許多不同的主題。我已經為這眾多的問題準備一段時間了,現在我將它們分享給你們。這里面不但包含經典的面試問題,如線程、集合、equals 和 hashcode、socket,而且還包含了 NIO、數組、字符串、Java 8 等主題。
該列表包含了入門級 Java 程序員和多年經驗的高級開發者的問題。無論你是 1、2、3、4、5、6、7、8、9 還是 10 年經驗的開發者,你都能在其中找到一些有趣的問題。這里包含了一些超級容易回答的問題,同時包含經驗豐富的 Java 程序員也會棘手的問題。
當然你們也是非常幸運的,當今有許多好的書來幫助你準備 Java 面試,其中有一本我覺得特別有用和有趣的是 Markham 的 Java 程序面試揭秘(Java Programming Interview Exposed)。 這本書會告訴你一些 Java 和 JEE 面試中最重要的主題,即使你不是準備 Java 面試,也值得一讀。
該問題列表特別長,我們有各個地方的問題,所以,答案必須要短小、簡潔、干脆,不拖泥帶水。因此,除了這一個段落,你只會聽到問題與答案,再無其他內容,沒有反饋,也沒有評價。為此,我已經寫好了一些博文,在這些文章中你可以找到我對某些問題的觀點,如我為什么喜歡這個問題,這個問題的挑戰是什么?期望從面試者那獲取到什么樣的答案?
這個列表有一點不同,我鼓勵你采用類似的方式去分享問題和答案,這樣容易溫習。我希望這個列表對面試官和候選人都有很好的用處,面試官可以對這些問題上做一些改變以獲取新奇和令人驚奇的元素,這對一次好的面試來說非常重要。而候選者,可以擴展和測試 Java 程序語言和平臺關鍵領域的知識。2015 年,會更多的關注并發概念,JVM 內部,32 位 JVM 和 64 JVM的區別,單元測試及整潔的代碼。我確信,如果你讀過這個龐大的 Java 面試問題列表,無論是電話面試還是面對面的面試,你都能有很好的表現。
## Java 面試中的重要話題
除了你看到的驚人的問題數量,我也盡量保證質量。我不止一次分享各個重要主題中的問題,也確保包含所謂的高級話題,這些話題很多程序員不喜歡準備或者直接放棄,因為他們的工作不會涉及到這些。Java NIO 和 JVM 底層就是最好的例子。你也可以將設計模式劃分到這一類中,但是越來越多有經驗的程序員了解 GOF 設計模式并應用這些模式。我也盡量在這個列表中包含 2015 年最新的面試問題,這些問題可能是來年關注的核心。為了給你一個大致的了解,下面列出這份 Java 面試問題列表包含的主題:
多線程,并發及線程基礎
數據類型轉換的基本原則
垃圾回收(GC)
Java 集合框架
數組
字符串
GOF 設計模式
SOLID (**單一功能、開閉原則、里氏替換、接口隔離**以及**依賴反轉**)設計原則
抽象類與接口
Java 基礎,如 equals 和 hashcode
泛型與枚舉
Java IO 與 NIO
常用網絡協議
Java 中的數據結構和算法
正則表達式
JVM 底層
Java 最佳實踐
JDBC
Date, Time 與 Calendar
Java 處理 XML
JUnit
編程
## 120 大?[Java 面試題](http://forum.jobbole.com/showthread.php/1707 "常見Java面試題(有解答)")及答案
現在是時候給你展示我近 5 年從各種面試中收集來的 120 個問題了。我確定你在自己的面試中見過很多這些問題,很多問題你也能正確回答。
### 多線程、并發及線程的基礎問題
1)Java 中能創建 volatile 數組嗎?
能,Java 中可以創建 volatile 類型數組,不過只是一個指向數組的引用,而不是整個數組。我的意思是,如果改變引用指向的數組,將會受到 volatile 的保護,但是如果多個線程同時改變數組的元素,volatile 標示符就不能起到之前的保護作用了。
2)volatile 能使得一個非原子操作變成原子操作嗎?
一個典型的例子是在類中有一個 long 類型的成員變量。如果你知道該成員變量會被多個線程訪問,如計數器、價格等,你最好是將其設置為 volatile。為什么?因為 Java 中讀取 long 類型變量不是原子的,需要分成兩步,如果一個線程正在修改該 long 變量的值,另一個線程可能只能看到該值的一半(前 32 位)。但是對一個 volatile 型的 long 或 double 變量的讀寫是原子。
3)volatile 修飾符的有過什么實踐?
一種實踐是用 volatile 修飾 long 和 double 變量,使其能按原子類型來讀寫。double 和 long 都是64位寬,因此對這兩種類型的讀是分為兩部分的,第一次讀取第一個 32 位,然后再讀剩下的 32 位,這個過程不是原子的,但 Java 中 volatile 型的 long 或 double 變量的讀寫是原子的。volatile 修復符的另一個作用是提供內存屏障(memory barrier),例如在分布式框架中的應用。簡單的說,就是當你寫一個 volatile 變量之前,Java 內存模型會插入一個寫屏障(write barrier),讀一個 volatile 變量之前,會插入一個讀屏障(read barrier)。意思就是說,在你寫一個 volatile 域時,能保證任何線程都能看到你寫的值,同時,在寫之前,也能保證任何數值的更新對所有線程是可見的,因為內存屏障會將其他所有寫的值更新到緩存。
4)volatile 類型變量提供什么保證?([答案](http://java67.blogspot.sg/2012/08/what-is-volatile-variable-in-java-when.html))
volatile 變量提供順序和可見性保證,例如,JVM 或者 JIT為了獲得更好的性能會對語句重排序,但是 volatile 類型變量即使在沒有同步塊的情況下賦值也不會與其他語句重排序。 volatile 提供 happens-before 的保證,確保一個線程的修改能對其他線程是可見的。某些情況下,volatile 還能提供原子性,如讀 64 位數據類型,像 long 和 double 都不是原子的,但 volatile 類型的 double 和 long 就是原子的。
5) 10 個線程和 2 個線程的同步代碼,哪個更容易寫?
從寫代碼的角度來說,兩者的復雜度是相同的,因為同步代碼與線程數量是相互獨立的。但是同步策略的選擇依賴于線程的數量,因為越多的線程意味著更大的競爭,所以你需要利用同步技術,如鎖分離,這要求更復雜的代碼和專業知識。
6)你是如何調用 wait()方法的?使用 if 塊還是循環?為什么?([答案](http://javarevisited.blogspot.sg/2015/07/how-to-use-wait-notify-and-notifyall-in.html))
wait() 方法應該在循環調用,因為當線程獲取到 CPU 開始執行的時候,其他條件可能還沒有滿足,所以在處理前,循環檢測條件是否滿足會更好。下面是一段標準的使用 wait 和 notify 方法的代碼:
~~~
// The standard idiom for using the wait method
synchronized (obj) {
while (condition does not hold)
obj.wait(); // (Releases lock, and reacquires on wakeup)
... // Perform action appropriate to condition
}
~~~
參見?[Effective Java](http://www.amazon.com/gp/product/B000WJOUPA/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=B000WJOUPA&linkCode=as2&tag=job0ae-20 "Effective Java")?第 69 條,獲取更多關于為什么應該在循環中來調用 wait 方法的內容。
7)什么是多線程環境下的偽共享(false sharing)?
偽共享是多線程系統(每個處理器有自己的局部緩存)中一個眾所周知的性能問題。偽共享發生在不同處理器的上的線程對變量的修改依賴于相同的緩存行,如下圖所示:
[](http://jbcdn2.b0.upaiyun.com/2015/11/2bccd7f52a70db95aa72524ef3a55164.gif "最近5年133個Java面試問題列表")
### 有經驗程序員的 Java 面試題
偽共享問題很難被發現,因為線程可能訪問完全不同的全局變量,內存中卻碰巧在很相近的位置上。如其他諸多的并發問題,避免偽共享的最基本方式是仔細審查代碼,根據緩存行來調整你的數據結構。
8)什么是 Busy spin?我們為什么要使用它?
Busy spin 是一種在不釋放 CPU 的基礎上等待事件的技術。它經常用于避免丟失 CPU 緩存中的數據(如果線程先暫停,之后在其他CPU上運行就會丟失)。所以,如果你的工作要求低延遲,并且你的線程目前沒有任何順序,這樣你就可以通過循環檢測隊列中的新消息來代替調用 sleep() 或 wait() 方法。它唯一的好處就是你只需等待很短的時間,如幾微秒或幾納秒。LMAX 分布式框架是一個高性能線程間通信的庫,該庫有一個 BusySpinWaitStrategy 類就是基于這個概念實現的,使用 busy spin 循環 EventProcessors 等待屏障。
9)Java 中怎么獲取一份線程 dump 文件?
在 Linux 下,你可以通過命令 kill -3 PID (Java 進程的進程 ID)來獲取 Java 應用的 dump 文件。在 Windows 下,你可以按下 Ctrl + Break 來獲取。這樣 JVM 就會將線程的 dump 文件打印到標準輸出或錯誤文件中,它可能打印在控制臺或者日志文件中,具體位置依賴應用的配置。如果你使用Tomcat。
10)Swing 是線程安全的?([答案](http://javarevisited.blogspot.sg/2013/08/why-swing-is-not-thread-safe-in-java-Swingworker-Event-thread.html))
不是,Swing 不是線程安全的。你不能通過任何線程來更新 Swing 組件,如 JTable、JList 或 JPanel,事實上,它們只能通過 GUI 或 AWT 線程來更新。這就是為什么 Swing 提供 invokeAndWait() 和 invokeLater() 方法來獲取其他線程的 GUI 更新請求。這些方法將更新請求放入 AWT 的線程隊列中,可以一直等待,也可以通過異步更新直接返回結果。你也可以在參考答案中查看和學習到更詳細的內容。
11)什么是線程局部變量?([答案](http://javarevisited.blogspot.sg/2012/05/how-to-use-threadlocal-in-java-benefits.html))
線程局部變量是局限于線程內部的變量,屬于線程自身所有,不在多個線程間共享。Java 提供 ThreadLocal 類來支持線程局部變量,是一種實現線程安全的方式。但是在管理環境下(如 web 服務器)使用線程局部變量的時候要特別小心,在這種情況下,工作線程的生命周期比任何應用變量的生命周期都要長。任何線程局部變量一旦在工作完成后沒有釋放,Java 應用就存在內存泄露的風險。
12)用 wait-notify 寫一段代碼來解決生產者-消費者問題?([答案](http://java67.blogspot.sg/2012/12/producer-consumer-problem-with-wait-and-notify-example.html))
請參考答案中的示例代碼。只要記住在同步塊中調用 wait() 和 notify()方法,如果阻塞,通過循環來測試等待條件。
13) 用 Java 寫一個線程安全的單例模式(Singleton)?([答案](http://javarevisited.blogspot.in/2012/12/how-to-create-thread-safe-singleton-in-java-example.html))
請參考答案中的示例代碼,這里面一步一步教你創建一個線程安全的 Java 單例類。當我們說線程安全時,意思是即使初始化是在多線程環境中,仍然能保證單個實例。Java 中,使用枚舉作為單例類是最簡單的方式來創建線程安全單例模式的方式。
14)Java 中 sleep 方法和 wait 方法的區別?([答案](http://java67.blogspot.sg/2012/08/what-are-difference-between-wait-and.html))
雖然兩者都是用來暫停當前運行的線程,但是 sleep() 實際上只是短暫停頓,因為它不會釋放鎖,而 wait() 意味著條件等待,這就是為什么該方法要釋放鎖,因為只有這樣,其他等待的線程才能在滿足條件時獲取到該鎖。
15)什么是不可變對象(immutable object)?Java 中怎么創建一個不可變對象?([答案](http://javarevisited.blogspot.sg/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html))
不可變對象指對象一旦被創建,狀態就不能再改變。任何修改都會創建一個新的對象,如 String、Integer及其它包裝類。詳情參見答案,一步一步指導你在 Java 中創建一個不可變的類。
16)我們能創建一個包含可變對象的不可變對象嗎?
是的,我們是可以創建一個包含可變對象的不可變對象的,你只需要謹慎一點,不要共享可變對象的引用就可以了,如果需要變化時,就返回原對象的一個拷貝。最常見的例子就是對象中包含一個日期對象的引用。
### 數據類型和 Java 基礎面試問題
17)Java 中應該使用什么數據類型來代表價格?([答案](http://javarevisited.blogspot.sg/2012/02/java-mistake-1-using-float-and-double.html))
如果不是特別關心內存和性能的話,使用BigDecimal,否則使用預定義精度的 double 類型。
18)怎么將 byte 轉換為 String?([答案](http://javarevisited.blogspot.sg/2014/08/2-examples-to-convert-byte-array-to-String-in-Java.html))
可以使用 String 接收 byte[] 參數的構造器來進行轉換,需要注意的點是要使用的正確的編碼,否則會使用平臺默認編碼,這個編碼可能跟原來的編碼相同,也可能不同。
19)Java 中怎樣將 bytes 轉換為 long 類型?
這個問題你來回答 :-)
20)我們能將 int 強制轉換為 byte 類型的變量嗎?如果該值大于 byte 類型的范圍,將會出現什么現象?
是的,我們可以做強制轉換,但是 Java 中 int 是 32 位的,而 byte 是 8 位的,所以,如果強制轉化是,int 類型的高 24 位將會被丟棄,byte 類型的范圍是從 -128 到 128。
21)存在兩個類,B 繼承 A,C 繼承 B,我們能將 B 轉換為 C 么?如 C = (C) B;([answer](http://javarevisited.blogspot.sg/2012/12/what-is-type-casting-in-java-class-interface-example.html)答案)
22)哪個類包含 clone 方法?是 Cloneable 還是 Object?([答案](http://javarevisited.blogspot.sg/2015/01/java-clone-tutorial-part-2-overriding-with-mutable-field-example.html))
java.lang.Cloneable 是一個標示性接口,不包含任何方法,clone 方法在 object 類中定義。并且需要知道 clone() 方法是一個本地方法,這意味著它是由 c 或 c++ 或 其他本地語言實現的。
23)Java 中 ++ 操作符是線程安全的嗎?(答案)
23)不是線程安全的操作。它涉及到多個指令,如讀取變量值,增加,然后存儲回內存,這個過程可能會出現多個線程交差。
24)a = a + b 與 a += b 的區別(答案)
+= 隱式的將加操作的結果類型強制轉換為持有結果的類型。如果兩這個整型相加,如 byte、short 或者 int,首先會將它們提升到 int 類型,然后在執行加法操作。如果加法操作的結果比 a 的最大值要大,則 a+b 會出現編譯錯誤,但是 a += b 沒問題,如下:
byte a = 127;
byte b = 127;
b = a + b; // error : cannot convert from int to byte
b += a; // ok
(譯者注:這個地方應該表述的有誤,其實無論 a+b 的值為多少,編譯器都會報錯,因為 a+b 操作會將 a、b 提升為 int 類型,所以將 int 類型賦值給 byte 就會編譯出錯)
25)我能在不進行強制轉換的情況下將一個 double 值賦值給 long 類型的變量嗎?([答案](http://java67.blogspot.com/2014/11/how-to-convert-double-to-long-in-java-example.html))
不行,你不能在沒有強制類型轉換的前提下將一個 double 值賦值給 long 類型的變量,因為 double 類型的范圍比 long 類型更廣,所以必須要進行強制轉換。
26)3*0.1 == 0.3 將會返回什么?true 還是 false?(答案)
false,因為有些浮點數不能完全精確的表示出來。
27)int 和 Integer 哪個會占用更多的內存?(答案)
Integer 對象會占用更多的內存。Integer 是一個對象,需要存儲對象的元數據。但是 int 是一個原始類型的數據,所以占用的空間更少。
28)為什么 Java 中的 String 是不可變的(Immutable)?([answer](http://java67.blogspot.sg/2014/01/why-string-class-has-made-immutable-or-final-java.html)答案)
Java 中的 String 不可變是因為 Java 的設計者認為字符串使用非常頻繁,將字符串設置為不可變可以允許多個客戶端之間共享相同的字符串。更詳細的內容參見答案。
29)我們能在 Switch 中使用 String 嗎?([answer](http://javarevisited.blogspot.sg/2011/08/string-switch-case-jdk7-example.html)答案)
從 Java 7 開始,我們可以在 switch case 中使用字符串,但這僅僅是一個語法糖。內部實現在 switch 中使用字符串的 hash code。
30)Java 中的構造器鏈是什么?([answer](http://java67.blogspot.sg/2012/12/how-constructor-chaining-works-in-java.html)答案)
當你從一個構造器中調用另一個構造器,就是Java 中的構造器鏈。這種情況只在重載了類的構造器的時候才會出現。
### JVM 底層 與 GC(Garbage Collection) 的面試問題
31)64 位 JVM 中,int 的長度是多數?
Java 中,int 類型變量的長度是一個固定值,與平臺無關,都是 32 位。意思就是說,在 32 位 和 64 位 的Java 虛擬機中,int 類型的長度是相同的。
32)Serial 與 Parallel GC之間的不同之處?([答案](http://javarevisited.blogspot.sg/2011/04/garbage-collection-in-java.html))
Serial 與 Parallel 在GC執行的時候都會引起 stop-the-world。它們之間主要不同 serial 收集器是默認的復制收集器,執行 GC 的時候只有一個線程,而 parallel 收集器使用多個 GC 線程來執行。
33)32 位和 64 位的 JVM,int 類型變量的長度是多數?(答案)
32 位和 64 位的 JVM 中,int 類型變量的長度是相同的,都是 32 位或者 4 個字節。
34)Java 中 WeakReference 與 SoftReference的區別?([答案](http://javarevisited.blogspot.sg/2014/03/difference-between-weakreference-vs-softreference-phantom-strong-reference-java.html))
雖然 WeakReference 與 SoftReference 都有利于提高 GC 和 內存的效率,但是 WeakReference ,一旦失去最后一個強引用,就會被 GC 回收,而軟引用雖然不能阻止被回收,但是可以延遲到 JVM 內存不足的時候。
35)WeakHashMap 是怎么工作的?(答案)
WeakHashMap 的工作與正常的 HashMap 類似,但是使用弱引用作為 key,意思就是當 key 對象沒有任何引用時,key/value 將會被回收。
36)JVM 選項 -XX:+UseCompressedOops 有什么作用?為什么要使用?(答案)
當你將你的應用從 32 位的 JVM 遷移到 64 位的 JVM 時,由于對象的指針從 32 位增加到了 64 位,因此堆內存會突然增加,差不多要翻倍。這也會對 CPU 緩存(容量比內存小很多)的數據產生不利的影響。因為,遷移到 64 位的 JVM 主要動機在于可以指定最大堆大小,通過壓縮 OOP 可以節省一定的內存。通過 -XX:+UseCompressedOops 選項,JVM 會使用 32 位的 OOP,而不是 64 位的 OOP。
37)怎樣通過 Java 程序來判斷 JVM 是 32 位 還是 64 位?([答案](http://javarevisited.blogspot.sg/2012/01/find-jvm-is-32-or-64-bit-java-program.html))
你可以檢查某些系統屬性如 sun.arch.data.model 或 os.arch 來獲取該信息。
38)32 位 JVM 和 64 位 JVM 的最大堆內存分別是多數?([答案](http://javarevisited.blogspot.sg/2013/04/what-is-maximum-heap-size-for-32-bit-64-JVM-Java-memory.html))
理論上說上 32 位的 JVM 堆內存可以到達 2^32,即 4GB,但實際上會比這個小很多。不同操作系統之間不同,如 Windows 系統大約 1.5 GB,Solaris 大約 3GB。64 位 JVM允許指定最大的堆內存,理論上可以達到 2^64,這是一個非常大的數字,實際上你可以指定堆內存大小到 100GB。甚至有的 JVM,如 Azul,堆內存到 1000G 都是可能的。
39)JRE、JDK、JVM 及 JIT 之間有什么不同?([答案](http://javarevisited.blogspot.sg/2011/12/jre-jvm-jdk-jit-in-java-programming.html))
JRE 代表 Java 運行時(Java run-time),是運行 Java 引用所必須的。JDK 代表 Java 開發工具(Java development kit),是 Java 程序的開發工具,如 Java 編譯器,它也包含 JRE。JVM 代表 Java 虛擬機(Java virtual machine),它的責任是運行 Java 應用。JIT 代表即時編譯(Just In Time compilation),當代碼執行的次數超過一定的閾值時,會將 Java 字節碼轉換為本地代碼,如,主要的熱點代碼會被準換為本地代碼,這樣有利大幅度提高 Java 應用的性能。
[](http://jbcdn2.b0.upaiyun.com/2015/11/4468a2440b48658c08acc50f15c3985b.jpg "最近5年133個Java面試問題列表")
3 年工作經驗的 Java 面試題
40)解釋 Java 堆空間及 GC?([答案](http://javarevisited.blogspot.sg/2011/05/java-heap-space-memory-size-jvm.html))
當通過 Java 命令啟動 Java 進程的時候,會為它分配內存。內存的一部分用于創建堆空間,當程序中創建對象的時候,就從對空間中分配內存。GC 是 JVM 內部的一個進程,回收無效對象的內存用于將來的分配。
[](http://jbcdn2.b0.upaiyun.com/2015/11/7ce5bea27bd3671ceab81f17629b395b.jpg "最近5年133個Java面試問題列表")
### JVM 底層面試題及答案
41)你能保證 GC 執行嗎?(答案)
不能,雖然你可以調用 System.gc() 或者 Runtime.gc(),但是沒有辦法保證 GC 的執行。
42)怎么獲取 Java 程序使用的內存?堆使用的百分比?
可以通過 java.lang.Runtime 類中與內存相關方法來獲取剩余的內存,總內存及最大堆內存。通過這些方法你也可以獲取到堆使用的百分比及堆內存的剩余空間。Runtime.freeMemory() 方法返回剩余空間的字節數,Runtime.totalMemory() 方法總內存的字節數,Runtime.maxMemory() 返回最大內存的字節數。
43)Java 中堆和棧有什么區別?([答案](http://javarevisited.blogspot.com/2013/01/difference-between-stack-and-heap-java.html))
JVM 中堆和棧屬于不同的內存區域,使用目的也不同。棧常用于保存方法幀和局部變量,而對象總是在堆上分配。棧通常都比堆小,也不會在多個線程之間共享,而堆被整個 JVM 的所有線程共享。
[](http://jbcdn2.b0.upaiyun.com/2015/11/1495374ba77fdf61435e38755773cc30.gif "最近5年133個Java面試問題列表")
### 關于內存的的面試問題和答案
### Java 基本概念面試題
44)“a==b”和”a.equals(b)”有什么區別?([答案](http://javarevisited.blogspot.sg/2012/12/difference-between-equals-method-and-equality-operator-java.html))
如果 a 和 b 都是對象,則 a==b 是比較兩個對象的引用,只有當 a 和 b 指向的是堆中的同一個對象才會返回 true,而 a.equals(b) 是進行邏輯比較,所以通常需要重寫該方法來提供邏輯一致性的比較。例如,String 類重寫 equals() 方法,所以可以用于兩個不同對象,但是包含的字母相同的比較。
45)a.hashCode() 有什么用?與 a.equals(b) 有什么關系?([答案](http://javarevisited.blogspot.sg/2011/10/override-hashcode-in-java-example.html))
hashCode() 方法是相應對象整型的 hash 值。它常用于基于 hash 的集合類,如 Hashtable、HashMap、LinkedHashMap等等。它與 equals() 方法關系特別緊密。根據 Java 規范,兩個使用 equal() 方法來判斷相等的對象,必須具有相同的 hash code。
46)final、finalize 和 finally 的不同之處?([答案](http://javarevisited.blogspot.sg/2012/11/difference-between-final-finally-and-finalize-java.html))
final 是一個修飾符,可以修飾變量、方法和類。如果 final 修飾變量,意味著該變量的值在初始化后不能被改變。finalize 方法是在對象被回收之前調用的方法,給對象自己最后一個復活的機會,但是什么時候調用 finalize 沒有保證。finally 是一個關鍵字,與 try 和 catch 一起用于異常的處理。finally 塊一定會被執行,無論在 try 塊中是否有發生異常。
47)Java 中的編譯期常量是什么?使用它又什么風險?
公共靜態不可變(public static final )變量也就是我們所說的編譯期常量,這里的 public 可選的。實際上這些變量在編譯時會被替換掉,因為編譯器知道這些變量的值,并且知道這些變量在運行時不能改變。這種方式存在的一個問題是你使用了一個內部的或第三方庫中的公有編譯時常量,但是這個值后面被其他人改變了,但是你的客戶端仍然在使用老的值,甚至你已經部署了一個新的jar。為了避免這種情況,當你在更新依賴 JAR 文件時,確保重新編譯你的程序。
### Java 集合框架的面試題
這部分也包含數據結構、算法及數組的面試問題
48) List、Set、Map 和 Queue 之間的區別(答案)
List 是一個有序集合,允許元素重復。它的某些實現可以提供基于下標值的常量訪問時間,但是這不是 List 接口保證的。Set 是一個無序集合。
49)poll() 方法和 remove() 方法的區別?
poll() 和 remove() 都是從隊列中取出一個元素,但是 poll() 在獲取元素失敗的時候會返回空,但是 remove() 失敗的時候會拋出異常。
50)Java 中 LinkedHashMap 和 PriorityQueue 的區別是什么?([答案](http://javarevisited.blogspot.sg/2013/10/what-is-priorityqueue-data-structure-java-example-tutorial.html))
PriorityQueue 保證最高或者最低優先級的的元素總是在隊列頭部,但是 LinkedHashMap 維持的順序是元素插入的順序。當遍歷一個 PriorityQueue 時,沒有任何順序保證,但是 LinkedHashMap 課保證遍歷順序是元素插入的順序。
51)ArrayList 與 LinkedList 的不區別?([答案](http://java67.blogspot.sg/2012/12/difference-between-arraylist-vs-LinkedList-java.html))
最明顯的區別是 ArrrayList 底層的數據結構是數組,支持隨機訪問,而 LinkedList 的底層數據結構書鏈表,不支持隨機訪問。使用下標訪問一個元素,ArrayList 的時間復雜度是 O(1),而 LinkedList 是 O(n)。更多細節的討論參見答案。
52)用哪兩種方式來實現集合的排序?([答案](http://java67.blogspot.sg/2012/07/sort-list-ascending-descending-order-set-arraylist.html))
你可以使用有序集合,如 TreeSet 或 TreeMap,你也可以使用有順序的的集合,如 list,然后通過 Collections.sort() 來排序。
53)Java 中怎么打印數組?([answer](http://java67.blogspot.sg/2014/03/how-to-print-array-in-java-example-tutorial.html)答案)
你可以使用 Arrays.toString() 和 Arrays.deepToString() 方法來打印數組。由于數組沒有實現 toString() 方法,所以如果將數組傳遞給 System.out.println() 方法,將無法打印出數組的內容,但是 Arrays.toString() 可以打印每個元素。
54)Java 中的 LinkedList 是單向鏈表還是雙向鏈表?(答案)
是雙向鏈表,你可以檢查 JDK 的源碼。在 Eclipse,你可以使用快捷鍵 Ctrl + T,直接在編輯器中打開該類。
55)Java 中的 TreeMap 是采用什么樹實現的?(答案)
Java 中的 TreeMap 是使用紅黑樹實現的。
56) Hashtable 與 HashMap 有什么不同之處?([答案](http://java67.blogspot.sg/2012/08/5-difference-between-hashtable-hashmap-Java-collection.html))
這兩個類有許多不同的地方,下面列出了一部分:
a) Hashtable 是 JDK 1 遺留下來的類,而 HashMap 是后來增加的。
b)Hashtable 是同步的,比較慢,但 HashMap 沒有同步策略,所以會更快。
c)Hashtable 不允許有個空的 key,但是 HashMap 允許出現一個 null key。
更多的不同之處參見答案。
57)Java 中的 HashSet,內部是如何工作的?([answer](http://java67.blogspot.sg/2014/01/how-hashset-is-implemented-or-works-internally-java.html)答案)
HashSet 的內部采用 HashMap來實現。由于 Map 需要 key 和 value,所以所有 key 的都有一個默認 value。類似于 HashMap,HashSet 不允許重復的 key,只允許有一個null key,意思就是 HashSet 中只允許存儲一個 null 對象。
58)寫一段代碼在遍歷 ArrayList 時移除一個元素?([答案](http://javarevisited.blogspot.sg/2014/01/ow-to-remove-objects-from-collection-arraylist-java-iterator-traversing.html))
該問題的關鍵在于面試者使用的是 ArrayList 的 remove() 還是 Iterator 的 remove()方法。這有一段[示例代碼](http://java67.blogspot.com/2015/10/how-to-solve-concurrentmodificationexception-in-java-arraylist.html),是使用正確的方式來實現在遍歷的過程中移除元素,而不會出現 ConcurrentModificationException 異常的示例代碼。
59)我們能自己寫一個容器類,然后使用 for-each 循環碼?
可以,你可以寫一個自己的容器類。如果你想使用 Java 中增強的循環來遍歷,你只需要實現 Iterable 接口。如果你實現 Collection 接口,默認就具有該屬性。
60)ArrayList 和 HashMap 的默認大小是多數?([答案](http://javarevisited.blogspot.sg/2014/07/java-optimization-empty-arraylist-and-Hashmap-cost-less-memory-jdk-17040-update.html))
在 Java 7 中,ArrayList 的默認大小是 10 個元素,HashMap 的默認大小是16個元素(必須是2的冪)。這就是 Java 7 中 ArrayList 和 HashMap 類的代碼片段:
~~~
// from ArrayList.java JDK 1.7
private static final int DEFAULT_CAPACITY = 10;
//from HashMap.java JDK 7
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
~~~
61)有沒有可能兩個不相等的對象有有相同的 hashcode?
有可能,兩個不相等的對象可能會有相同的 hashcode 值,這就是為什么在 hashmap 中會有沖突。相等 hashcode 值的規定只是說如果兩個對象相等,必須有相同的hashcode 值,但是沒有關于不相等對象的任何規定。
62)兩個相同的對象會有不同的的 hash code 嗎?
不能,根據 hash code 的規定,這是不可能的。
63)我們可以在 hashcode() 中使用隨機數字嗎?([答案](http://javarevisited.blogspot.sg/2011/10/override-hashcode-in-java-example.html))
不行,因為對象的 hashcode 值必須是相同的。參見答案獲取更多關于 Java 中重寫 hashCode() 方法的知識。
64)Java 中,Comparator 與 Comparable 有什么不同?([答案](http://java67.blogspot.sg/2013/08/difference-between-comparator-and-comparable-in-java-interface-sorting.html))
Comparable 接口用于定義對象的自然順序,而 comparator 通常用于定義用戶定制的順序。Comparable 總是只有一個,但是可以有多個 comparator 來定義對象的順序。
65)為什么在重寫 equals 方法的時候需要重寫 hashCode 方法?([答案](http://javarevisited.blogspot.sg/2015/01/why-override-equals-hashcode-or-tostring-java.html))
因為有強制的規范指定需要同時重寫 hashcode 與 equal 是方法,許多容器類,如 HashMap、HashSet 都依賴于 hashcode 與 equals 的規定。
### Java IO 和 NIO 的面試題
IO 是 Java 面試中一個非常重要的點。你應該很好掌握 Java IO,NIO,NIO2 以及與操作系統,磁盤 IO 相關的基礎知識。下面是 Java IO 中經常問的問題。
66)在我 Java 程序中,我有三個 socket,我需要多少個線程來處理?
67)Java 中怎么創建 ByteBuffer?
68)Java 中,怎么讀寫 ByteBuffer ?
69)Java 采用的是大端還是小端?
70)ByteBuffer 中的字節序是什么?
71)Java 中,直接緩沖區與非直接緩沖器有什么區別?([答案](http://javarevisited.blogspot.sg/2015/08/difference-between-direct-non-direct-mapped-bytebuffer-nio-java.html))
72)Java 中的內存映射緩存區是什么?([answer](http://javarevisited.blogspot.sg/2012/01/memorymapped-file-and-io-in-java.html)答案)
73)socket 選項 TCP NO DELAY 是指什么?
74)TCP 協議與 UDP 協議有什么區別?([answer](http://javarevisited.blogspot.com/2014/07/9-difference-between-tcp-and-udp-protocol.html)答案)
75)Java 中,ByteBuffer 與 StringBuffer有什么區別?(答案)
### Java 最佳實踐的面試問題
包含 Java 中各個部分的最佳實踐,如集合,字符串,IO,多線程,錯誤和異常處理,設計模式等等。
76)Java 中,編寫多線程程序的時候你會遵循哪些最佳實踐?([答案](http://javarevisited.blogspot.com/2015/05/top-10-java-multithreading-and.html))
這是我在寫Java 并發程序的時候遵循的一些最佳實踐:
a)給線程命名,這樣可以幫助調試。
b)最小化同步的范圍,而不是將整個方法同步,只對關鍵部分做同步。
c)如果可以,更偏向于使用 volatile 而不是 synchronized。
d)使用更高層次的并發工具,而不是使用 wait() 和 notify() 來實現線程間通信,如 BlockingQueue,CountDownLatch 及 Semeaphore。
e)優先使用并發集合,而不是對集合進行同步。并發集合提供更好的可擴展性。
77)說出幾點 Java 中使用 Collections 的最佳實踐(答案)
這是我在使用 Java 中 Collectionc 類的一些最佳實踐:
a)使用正確的集合類,例如,如果不需要同步列表,使用 ArrayList 而不是 Vector。
b)優先使用并發集合,而不是對集合進行同步。并發集合提供更好的可擴展性。
c)使用接口代表和訪問集合,如使用List存儲 ArrayList,使用 Map 存儲 HashMap 等等。
d)使用迭代器來循環集合。
e)使用集合的時候使用泛型。
78)說出至少 5 點在 Java 中使用線程的最佳實踐。([答案](http://java67.blogspot.com/2014/01/10-points-about-thread-and-javalangthread-in-java.html))
這個問題與之前的問題類似,你可以使用上面的答案。對線程來說,你應該:
a)對線程命名
b)將線程和任務分離,使用線程池執行器來執行 Runnable 或 Callable。
c)使用線程池
79)說出 5 條 IO 的最佳實踐(答案)
IO 對 Java 應用的性能非常重要。理想情況下,你不應該在你應用的關鍵路徑上避免 IO 操作。下面是一些你應該遵循的 Java IO 最佳實踐:
a)使用有緩沖區的 IO 類,而不要單獨讀取字節或字符。
b)使用 NIO 和 NIO2
c)在 finally 塊中關閉流,或者使用 try-with-resource 語句。
d)使用內存映射文件獲取更快的 IO。
80)列出 5 個應該遵循的 JDBC 最佳實踐([答案](http://javarevisited.blogspot.sg/2012/08/top-10-jdbc-best-practices-for-java.html))
有很多的最佳實踐,你可以根據你的喜好來例舉。下面是一些更通用的原則:
a)使用批量的操作來插入和更新數據
b)使用 PreparedStatement 來避免 SQL 異常,并提高性能。
c)使用數據庫連接池
d)通過列名來獲取結果集,不要使用列的下標來獲取。
81)說出幾條 Java 中方法重載的最佳實踐?([答案](http://javarevisited.blogspot.sg/2013/01/java-best-practices-method-overloading-constructor.html))
下面有幾條可以遵循的方法重載的最佳實踐來避免造成自動裝箱的混亂。
a)不要重載這樣的方法:一個方法接收 int 參數,而另個方法接收 Integer 參數。
b)不要重載參數數量一致,而只是參數順序不同的方法。
c)如果重載的方法參數個數多于 5 個,采用可變參數。
### Date、Time 及 Calendar 的面試題
82)在多線程環境下,SimpleDateFormat 是線程安全的嗎?([答案](http://javarevisited.blogspot.sg/2012/03/simpledateformat-in-java-is-not-thread.html))
不是,非常不幸,DateFormat 的所有實現,包括 SimpleDateFormat 都不是線程安全的,因此你不應該在多線程序中使用,除非是在對外線程安全的環境中使用,如 將 SimpleDateFormat 限制在 ThreadLocal 中。如果你不這么做,在解析或者格式化日期的時候,可能會獲取到一個不正確的結果。因此,從日期、時間處理的所有實踐來說,我強力推薦 joda-time 庫。
83)Java 中如何格式化一個日期?如格式化為 ddMMyyyy 的形式?([答案](http://javarevisited.blogspot.com/2011/09/convert-date-to-string-simpledateformat.html))
Java 中,可以使用 SimpleDateFormat 類或者 joda-time 庫來格式日期。DateFormat 類允許你使用多種流行的格式來格式化日期。參見答案中的示例代碼,代碼中演示了將日期格式化成不同的格式,如 dd-MM-yyyy 或 ddMMyyyy。
84)Java 中,怎么在格式化的日期中顯示時區?([答案](http://java67.blogspot.sg/2013/01/how-to-format-date-in-java-simpledateformat-example.html))
85)Java 中 java.util.Date 與 java.sql.Date 有什么區別?([答案](http://java67.blogspot.sg/2014/02/how-to-convert-javautildate-to-javasqldate-example.html))
86)Java 中,如何計算兩個日期之間的差距?([程序](http://javarevisited.blogspot.sg/2015/07/how-to-find-number-of-days-between-two-dates-in-java.html))
87)Java 中,如何將字符串 YYYYMMDD 轉換為日期?([答案](http://java67.blogspot.sg/2014/12/string-to-date-example-in-java-multithreading.html))
### 單元測試 JUnit 面試題
89)如何測試靜態方法?(答案)
可以使用 PowerMock 庫來測試靜態方法。
90)怎么利用 JUnit 來測試一個方法的異常?([答案](http://javarevisited.blogspot.sg/2013/04/JUnit-tutorial-example-test-exception-thrown-by-java-method.html))
91)你使用過哪個單元測試庫來測試你的 Java 程序?(答案)
92)@Before 和 @BeforeClass 有什么區別?([答案](http://javarevisited.blogspot.sg/2013/04/JUnit-tutorial-example-test-exception-thrown-by-java-method.html))
### 編程和代碼相關的面試題
93)怎么檢查一個字符串只包含數字?([解決方案](http://java67.blogspot.com/2014/01/java-regular-expression-to-check-numbers-in-String.html))
94)Java 中如何利用泛型寫一個 LRU 緩存?(答案<)
95)寫一段 Java 程序將 byte 轉換為 long?(答案)
95)在不使用 StringBuffer 的前提下,怎么反轉一個字符串?([解決方案](http://java67.blogspot.com/2012/12/how-to-reverse-string-in-java-stringbuffer-stringbuilder.htm))
97)Java 中,怎么獲取一個文件中單詞出現的最高頻率?([解決方案](http://java67.blogspot.com/2015/10/java-program-to-find-repeated-words-and-count.html))
98)如何檢查出兩個給定的字符串是反序的?([解決方案](http://javarevisited.blogspot.sg/2013/03/Anagram-how-to-check-if-two-string-are-anagrams-example-tutorial.html))
99)Java 中,怎么打印出一個字符串的所有排列?([解決方案](http://javarevisited.blogspot.com/2015/08/how-to-find-all-permutations-of-string-java-example.html))
100)Java 中,怎樣才能打印出數組中的重復元素?([解決方案](http://javarevisited.blogspot.com/2015/06/3-ways-to-find-duplicate-elements-in-array-java.html))
101)Java 中如何將字符串轉換為整數?([解決方案](http://java67.blogspot.com/2015/08/2-ways-to-parse-string-to-int-in-java.html))
102)在沒有使用臨時變量的情況如何交換兩個整數變量的值?([解決方案](http://java67.blogspot.com/2015/08/how-to-swap-two-integers-without-using.html))
### 關于 OOP 和設計模式的面試題
這部分包含 Java 面試過程中關于 SOLID 的設計原則,OOP 基礎,如類,對象,接口,繼承,多態,封裝,抽象以及更高級的一些概念,如組合、聚合及關聯。也包含了 GOF 設計模式的問題。
103)接口是什么?為什么要使用接口而不是直接使用具體類?
接口用于定義 API。它定義了類必須得遵循的規則。同時,它提供了一種抽象,因為客戶端只使用接口,這樣可以有多重實現,如 List 接口,你可以使用可隨機訪問的 ArrayList,也可以使用方便插入和刪除的 LinkedList。接口中不允許寫代碼,以此來保證抽象,但是 Java 8 中你可以在接口聲明靜態的默認方法,這種方法是具體的。
104)Java 中,抽象類與接口之間有什么不同?([答案](http://javarevisited.blogspot.sg/2013/05/difference-between-abstract-class-vs-interface-java-when-prefer-over-design-oops.html))
Java 中,抽象類和接口有很多不同之處,但是最重要的一個是 Java 中限制一個類只能繼承一個類,但是可以實現多個接口。抽象類可以很好的定義一個家族類的默認行為,而接口能更好的定義類型,有助于后面實現多態機制。關于這個問題的討論請查看答案。
105)除了單例模式,你在生產環境中還用過什么設計模式?
這需要根據你的經驗來回答。一般情況下,你可以說依賴注入,工廠模式,裝飾模式或者觀察者模式,隨意選擇你使用過的一種即可。不過你要準備回答接下的基于你選擇的模式的問題。
106)你能解釋一下里氏替換原則嗎?([答案](http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-principles.html))
107) 什么情況下會違反迪米特法則?為什么會有這個問題?([答案](http://javarevisited.blogspot.com/2014/05/law-of-demeter-example-in-java.html))
迪米特法則建議“只和朋友說話,不要陌生人說話”,以此來減少類之間的耦合。
108)適配器模式是什么?什么時候使用?
適配器模式提供對接口的轉換。如果你的客戶端使用某些接口,但是你有另外一些接口,你就可以寫一個適配去來連接這些接口。
109)什么是“依賴注入”和“控制反轉”?為什么有人使用?([答案](http://javarevisited.blogspot.sg/2012/12/inversion-of-control-dependency-injection-design-pattern-spring-example-tutorial.html))
110)抽象類是什么?它與接口有什么區別?你為什么要使用過抽象類?([答案](http://java67.blogspot.sg/2014/06/why-abstract-class-is-important-in-java.html))
111)構造器注入和 setter 依賴注入,那種方式更好?([答案](http://javarevisited.blogspot.sg/2012/11/difference-between-setter-injection-vs-constructor-injection-spring-framework.html))
每種方式都有它的缺點和優點。構造器注入保證所有的注入都被初始化,但是 setter 注入提供更好的靈活性來設置可選依賴。如果使用 XML 來描述依賴,Setter 注入的可讀寫會更強。經驗法則是強制依賴使用構造器注入,可選依賴使用 setter 注入。
112)依賴注入和工程模式之間有什么不同?([答案](http://javarevisited.blogspot.sg/2015/06/difference-between-dependency-injection.html))
雖然兩種模式都是將對象的創建從應用的邏輯中分離,但是依賴注入比工程模式更清晰。通過依賴注入,你的類就是 POJO,它只知道依賴而不關心它們怎么獲取。使用工廠模式,你的類需要通過工廠來獲取依賴。因此,使用 DI 會比使用工廠模式更容易測試。關于這個話題的更詳細討論請參見答案。
113)適配器模式和裝飾器模式有什么區別?([答案](http://javarevisited.blogspot.sg/2015/01/adapter-vs-decorator-vs-facade-vs-proxy-pattern-java.html))
雖然適配器模式和裝飾器模式的結構類似,但是每種模式的出現意圖不同。適配器模式被用于橋接兩個接口,而裝飾模式的目的是在不修改類的情況下給類增加新的功能。
114)適配器模式和代理模式之前有什么不同?([答案](http://javarevisited.blogspot.sg/2015/01/adapter-vs-decorator-vs-facade-vs-proxy-pattern-java.html))
這個問題與前面的類似,適配器模式和代理模式的區別在于他們的意圖不同。由于適配器模式和代理模式都是封裝真正執行動作的類,因此結構是一致的,但是適配器模式用于接口之間的轉換,而代理模式則是增加一個額外的中間層,以便支持分配、控制或智能訪問。
115)什么是模板方法模式?(答案)
模板方法提供算法的框架,你可以自己去配置或定義步驟。例如,你可以將排序算法看做是一個模板。它定義了排序的步驟,但是具體的比較,可以使用 Comparable 或者其語言中類似東西,具體策略由你去配置。列出算法概要的方法就是眾所周知的模板方法。
116)什么時候使用訪問者模式?(答案)
訪問者模式用于解決在類的繼承層次上增加操作,但是不直接與之關聯。這種模式采用雙派發的形式來增加中間層。
117)什么時候使用組合模式?(答案)
組合模式使用樹結構來展示部分與整體繼承關系。它允許客戶端采用統一的形式來對待單個對象和對象容器。當你想要展示對象這種部分與整體的繼承關系時采用組合模式。
118)繼承和組合之間有什么不同?([答案](http://javarevisited.blogspot.sg/2015/06/difference-between-inheritance-and-Composition-in-Java-OOP.html))
雖然兩種都可以實現代碼復用,但是組合比繼承共靈活,因為組合允許你在運行時選擇不同的實現。用組合實現的代碼也比繼承測試起來更加簡單。
119)描述 Java 中的重載和重寫?([答案](http://java67.blogspot.sg/2012/09/difference-between-overloading-vs-overriding-in-java.html))
重載和重寫都允許你用相同的名稱來實現不同的功能,但是重載是編譯時活動,而重寫是運行時活動。你可以在同一個類中重載方法,但是只能在子類中重寫方法。重寫必須要有繼承。
120)Java 中,嵌套公共靜態類與頂級類有什么不同?([答案](http://javarevisited.blogspot.sg/2012/12/inner-class-and-nested-static-class-in-java-difference.html))
類的內部可以有多個嵌套公共靜態類,但是一個 Java 源文件只能有一個頂級公共類,并且頂級公共類的名稱與源文件名稱必須一致。
121) OOP 中的 組合、聚合和關聯有什么區別?([答案](http://javarevisited.blogspot.sg/2014/02/ifference-between-association-vs-composition-vs-aggregation.html))
如果兩個對象彼此有關系,就說他們是彼此相關聯的。組合和聚合是面向對象中的兩種形式的關聯。組合是一種比聚合更強力的關聯。組合中,一個對象是另一個的擁有者,而聚合則是指一個對象使用另一個對象。如果對象 A 是由對象 B 組合的,則 A 不存在的話,B一定不存在,但是如果 A 對象聚合了一個對象 B,則即使 A 不存在了,B 也可以單獨存在。
122)給我一個符合開閉原則的設計模式的例子?([答案](http://javarevisited.blogspot.sg/2011/11/great-example-of-open-closed-design.html))
開閉原則要求你的代碼對擴展開放,對修改關閉。這個意思就是說,如果你想增加一個新的功能,你可以很容易的在不改變已測試過的代碼的前提下增加新的代碼。有好幾個設計模式是基于開閉原則的,如策略模式,如果你需要一個新的策略,只需要實現接口,增加配置,不需要改變核心邏輯。一個正在工作的例子是 Collections.sort() 方法,這就是基于策略模式,遵循開閉原則的,你不需為新的對象修改 sort() 方法,你需要做的僅僅是實現你自己的 Comparator 接口。
123)抽象工廠模式和原型模式之間的區別?(答案)
124)什么時候使用享元模式?(答案)
享元模式通過共享對象來避免創建太多的對象。為了使用享元模式,你需要確保你的對象是不可變的,這樣你才能安全的共享。JDK 中 String 池、Integer 池以及 Long 池都是很好的使用了享元模式的例子。
### Java 面試中其他各式各樣的問題
這部分包含 Java 中關于 XML 的面試題,JDB[C 面試題](http://forum.jobbole.com/showthread.php/1730 "最全面的C/C++面試題"),正則表達式面試題,Java 錯誤和異常及序列化面試題
125)嵌套靜態類與頂級類有什么區別?([答案](http://java67.blogspot.sg/2012/10/nested-class-java-static-vs-non-static-inner.html))
一個公共的頂級類的源文件名稱與類名相同,而嵌套靜態類沒有這個要求。一個嵌套類位于頂級類內部,需要使用頂級類的名稱來引用嵌套靜態類,如 HashMap.Entry 是一個嵌套靜態類,HashMap 是一個頂級類,Entry是一個嵌套靜態類。
126)你能寫出一個正則表達式來判斷一個字符串是否是一個數字嗎?([解決方案](http://javarevisited.blogspot.sg/2012/10/regular-expression-example-in-java-to-check-String-number.html))
一個數字字符串,只能包含數字,如 0 到 9 以及 +、- 開頭,通過這個信息,你可以下一個如下的正則表達式來判斷給定的字符串是不是數字。
127)Java 中,受檢查異常 和 不受檢查異常的區別?([答案](http://java67.blogspot.sg/2012/12/difference-between-runtimeexception-and-checked-exception.html))
受檢查異常編譯器在編譯期間檢查。對于這種異常,方法強制處理或者通過 throws 子句聲明。其中一種情況是 Exception 的子類但不是 RuntimeException 的子類。非受檢查是 RuntimeException 的子類,在編譯階段不受編譯器的檢查。
128)Java 中,throw 和 throws 有什么區別?([答案](http://javarevisited.blogspot.sg/2012/02/difference-between-throw-and-throws-in.html))
throw 用于拋出 java.lang.Throwable 類的一個實例化對象,意思是說你可以通過關鍵字 throw 拋出一個 Error 或者 一個Exception,如:
throw new IllegalArgumentException(“size must be multiple of 2″)
而throws 的作用是作為方法聲明和簽名的一部分,方法被拋出相應的異常以便調用者能處理。Java 中,任何未處理的受檢查異常強制在 throws 子句中聲明。
129)Java 中,Serializable 與 Externalizable 的區別?([答案](http://javarevisited.blogspot.sg/2012/01/serializable-externalizable-in-java.html))
Serializable 接口是一個序列化 Java 類的接口,以便于它們可以在網絡上傳輸或者可以將它們的狀態保存在磁盤上,是 JVM 內嵌的默認序列化方式,成本高、脆弱而且不安全。Externalizable 允許你控制整個序列化過程,指定特定的二進制格式,增加安全機制。
130)Java 中,DOM 和 SAX 解析器有什么不同?([答案](http://javarevisited.blogspot.sg/2011/12/difference-between-dom-and-sax-parsers.html))
DOM 解析器將整個 XML 文檔加載到內存來創建一棵 DOM 模型樹,這樣可以更快的查找節點和修改 XML 結構,而 SAX 解析器是一個基于事件的解析器,不會將整個 XML 文檔加載到內存。由于這個原因,DOM 比 SAX 更快,也要求更多的內存,不適合于解析大 XML 文件。
131)說出 JDK 1.7 中的三個新特性?([答案](http://javarevisited.blogspot.sg/2014/04/10-jdk-7-features-to-revisit-before-you.html))
雖然 JDK 1.7 不像 JDK 5 和 8 一樣的大版本,但是,還是有很多新的特性,如 try-with-resource 語句,這樣你在使用流或者資源的時候,就不需要手動關閉,Java 會自動關閉。Fork-Join 池某種程度上實現 Java 版的 Map-reduce。允許 Switch 中有 String 變量和文本。菱形操作符(<>)用于類型推斷,不再需要在變量聲明的右邊申明泛型,因此可以寫出可讀寫更強、更簡潔的代碼。另一個值得一提的特性是改善異常處理,如允許在同一個 catch 塊中捕獲多個異常。
132)說出 5 個 JDK 1.8 引入的新特性?([答案](http://javarevisited.blogspot.sg/2014/02/10-example-of-lambda-expressions-in-java8.html))
Java 8 在 Java 歷史上是一個開創新的版本,下面 JDK 8 中 5 個主要的特性:
Lambda 表達式,允許像對象一樣傳遞匿名函數
Stream API,充分利用現代多核 CPU,可以寫出很簡潔的代碼
Date 與 Time API,最終,有一個穩定、簡單的日期和時間庫可供你使用
擴展方法,現在,接口中可以有靜態、默認方法。
重復注解,現在你可以將相同的注解在同一類型上使用多次。
133)Java 中,Maven 和 ANT 有什么區別?([答案](http://javarevisited.blogspot.sg/2015/01/difference-between-maven-ant-jenkins-and-hudson.html))
雖然兩者都是構建工具,都用于創建 Java 應用,但是 Maven 做的事情更多,在基于“約定優于配置”的概念下,提供標準的Java 項目結構,同時能為應用自動管理依賴(應用中所依賴的 JAR 文件),Maven 與 ANT 工具更多的不同之處請參見答案。
這就是所有的面試題,如此之多,是不是?我可以保證,如果你能回答列表中的所有問題,你就可以很輕松的應付任何核心 Java 或者高級 Java 面試。雖然,這里沒有涵蓋 Servlet、JSP、JSF、JPA,JMS,EJB 及其它 Java EE 技術,也沒有包含主流的框架如 Spring MVC,Struts 2.0,Hibernate,也沒有包含 SOAP 和 RESTful web service,但是這份列表對做 Java 開發的、準備應聘 Java web 開發職位的人還是同樣有用的,因為所有的 Java 面試,開始的問題都是 Java 基礎和 JDK API 相關的。如果你認為我這里有任何應該在這份列表中而被我遺漏了的 Java 流行的問題,你可以自由的給我建議。我的目的是從最近的面試中創建一份最新的、最優的 Java 面試問題列表。
## Java EE 相關的面試題
為了做 Java EE 的朋友,這里列出了一些 web 開發的特定問題,你們可以用來準備 JEE 部分的面試:
10 大 Spring 框架面試題及答案([參見](http://javarevisited.blogspot.sg/2011/09/spring-interview-questions-answers-j2ee.html))
10 個非常好的 XML 面試問題(Java 程序員)([參見](http://javarevisited.blogspot.sg/2013/01/10-xml-interview-questions-and-answers.html))
20 個非常好的設計模式面試問題([參見](http://java67.blogspot.com/2012/09/top-10-java-design-pattern-interview-question-answer.html))
10個最流行的 Struts 面試題(Java 開發者)([參見](http://javarevisited.blogspot.sg/2011/11/struts-interview-questions-answer-j2ee.html))
20 個 Tibco Rendezvous 及 EMS 的面試題([更多](http://javarevisited.blogspot.sg/2011/01/tibco-rv-interview-question-as-part.html))
10 個最頻繁被問到的 Servlet 面試問題及答案([參見](http://javarevisited.blogspot.sg/2011/09/servlet-interview-questions-answers.html))
20 個 jQuery 面試問題(Java Web 開發者)([列表](http://javarevisited.blogspot.sg/2015/02/top-16-jquery-interview-questions.html))
10 個非常好的 Oracle 面試問題(Java 開發者)([參見](http://javarevisited.blogspot.sg/2012/12/top-10-oracle-interview-questions-and-answers-database-sql.html))
10 大 來自 J2EE 面試中的 JSP 問題([更多](http://javarevisited.blogspot.sg/2011/10/jsp-interview-questions-answers-for.html))
12 個很好的 RESTful Web Services 面試問題([參見](http://javarevisited.blogspot.sg/2012/01/rest-web-services-framework-interview.html))
10 大 EJB 面試問題及答案([參見](http://javarevisited.blogspot.sg/2012/03/top-10-ejb-interview-question-and.html))
10 大 JMS 及 MQ 系列面試題及答案([列表](http://javarevisited.blogspot.sg/2014/03/top-10-websphere-mq-series-interview-questions-answers-active-rabbit.html))
10 個非常好 Hibernate 面試問題(Java EE 開發者)([參見](http://javarevisited.blogspot.sg/2013/05/10-hibernate-interview-questions-answers-java-j2ee-senior.html))
10 個非常好的 JDBC 面試題(Java 開發者)([參見](http://javarevisited.blogspot.sg/2012/12/top-10-jdbc-interview-questions-answers.html))
15 個 Java NIO 和網絡面試題及答案([參見](http://javarevisited.blogspot.sg/2014/08/socket-programming-networking-interview-questions-answers-Java.html))
10 大 XSLT 面試題及答案([更多](http://javarevisited.blogspot.sg/2013/05/10-xslt-or-xml-xsl-transformation-interview-questions-answers-java.html))
15 個來自 Java 面試的數據結構和算法問題([參見](http://javarevisited.blogspot.com/2013/03/top-15-data-structures-algorithm-interview-questions-answers-java-programming.html))
10 大 Java 面試難題及答案([參見](http://java67.blogspot.com/2012/09/top-10-tricky-java-interview-questions-answers.html))
40 個核心 Java 移動開發面試題及答案([列表](http://java67.blogspot.com/2015/03/top-40-core-java-interview-questions-answers-telephonic-round.html))
推薦給 Java 面試者的書籍
如果你正為 Java 面試尋找好的準備,你可以看一下下面的書籍,這些書籍包含了理論及編碼的相關問題
Markham 的 Java 編程面試揭秘([參見](http://www.amazon.com/Java-Programming-Interviews-Exposed-Markham/dp/1118722868?tag=javamysqlanta-20))
破解編碼面試:150 個編程問題及解答([參見](http://www.amazon.com/dp/098478280X/?tag=javamysqlanta-20))
程序面試揭秘:尋找下一份工作的秘密([參見](http://www.amazon.com/dp/1118261364/?tag=javamysqlanta-20))
原文鏈接:?[javarevisited](http://javarevisited.blogspot.kr/2015/10/133-java-interview-questions-answers-from-last-5-years.html)?翻譯:?[ImportNew.com?](http://www.importnew.com/)-?[paddx](http://www.importnew.com/author/paddx)
譯文鏈接:?[http://www.importnew.com/17232.html](http://www.importnew.com/17232.html)
[?**轉載請保留原文出處、譯者和譯文鏈接。**]
- JVM
- 深入理解Java內存模型
- 深入理解Java內存模型(一)——基礎
- 深入理解Java內存模型(二)——重排序
- 深入理解Java內存模型(三)——順序一致性
- 深入理解Java內存模型(四)——volatile
- 深入理解Java內存模型(五)——鎖
- 深入理解Java內存模型(六)——final
- 深入理解Java內存模型(七)——總結
- Java內存模型
- Java內存模型2
- 堆內內存還是堆外內存?
- JVM內存配置詳解
- Java內存分配全面淺析
- 深入Java核心 Java內存分配原理精講
- jvm常量池
- JVM調優總結
- JVM調優總結(一)-- 一些概念
- JVM調優總結(二)-一些概念
- VM調優總結(三)-基本垃圾回收算法
- JVM調優總結(四)-垃圾回收面臨的問題
- JVM調優總結(五)-分代垃圾回收詳述1
- JVM調優總結(六)-分代垃圾回收詳述2
- JVM調優總結(七)-典型配置舉例1
- JVM調優總結(八)-典型配置舉例2
- JVM調優總結(九)-新一代的垃圾回收算法
- JVM調優總結(十)-調優方法
- 基礎
- Java 征途:行者的地圖
- Java程序員應該知道的10個面向對象理論
- Java泛型總結
- 序列化與反序列化
- 通過反編譯深入理解Java String及intern
- android 加固防止反編譯-重新打包
- volatile
- 正確使用 Volatile 變量
- 異常
- 深入理解java異常處理機制
- Java異常處理的10個最佳實踐
- Java異常處理手冊和最佳實踐
- Java提高篇——對象克隆(復制)
- Java中如何克隆集合——ArrayList和HashSet深拷貝
- Java中hashCode的作用
- Java提高篇之hashCode
- 常見正則表達式
- 類
- 理解java類加載器以及ClassLoader類
- 深入探討 Java 類加載器
- 類加載器的工作原理
- java反射
- 集合
- HashMap的工作原理
- ConcurrentHashMap之實現細節
- java.util.concurrent 之ConcurrentHashMap 源碼分析
- HashMap的實現原理和底層數據結構
- 線程
- 關于Java并發編程的總結和思考
- 40個Java多線程問題總結
- Java中的多線程你只要看這一篇就夠了
- Java多線程干貨系列(1):Java多線程基礎
- Java非阻塞算法簡介
- Java并發的四種風味:Thread、Executor、ForkJoin和Actor
- Java中不同的并發實現的性能比較
- JAVA CAS原理深度分析
- 多個線程之間共享數據的方式
- Java并發編程
- Java并發編程(1):可重入內置鎖
- Java并發編程(2):線程中斷(含代碼)
- Java并發編程(3):線程掛起、恢復與終止的正確方法(含代碼)
- Java并發編程(4):守護線程與線程阻塞的四種情況
- Java并發編程(5):volatile變量修飾符—意料之外的問題(含代碼)
- Java并發編程(6):Runnable和Thread實現多線程的區別(含代碼)
- Java并發編程(7):使用synchronized獲取互斥鎖的幾點說明
- Java并發編程(8):多線程環境中安全使用集合API(含代碼)
- Java并發編程(9):死鎖(含代碼)
- Java并發編程(10):使用wait/notify/notifyAll實現線程間通信的幾點重要說明
- java并發編程-II
- Java多線程基礎:進程和線程之由來
- Java并發編程:如何創建線程?
- Java并發編程:Thread類的使用
- Java并發編程:synchronized
- Java并發編程:Lock
- Java并發編程:volatile關鍵字解析
- Java并發編程:深入剖析ThreadLocal
- Java并發編程:CountDownLatch、CyclicBarrier和Semaphore
- Java并發編程:線程間協作的兩種方式:wait、notify、notifyAll和Condition
- Synchronized與Lock
- JVM底層又是如何實現synchronized的
- Java synchronized詳解
- synchronized 與 Lock 的那點事
- 深入研究 Java Synchronize 和 Lock 的區別與用法
- JAVA編程中的鎖機制詳解
- Java中的鎖
- TreadLocal
- 深入JDK源碼之ThreadLocal類
- 聊一聊ThreadLocal
- ThreadLocal
- ThreadLocal的內存泄露
- 多線程設計模式
- Java多線程編程中Future模式的詳解
- 原子操作(CAS)
- [譯]Java中Wait、Sleep和Yield方法的區別
- 線程池
- 如何合理地估算線程池大小?
- JAVA線程池中隊列與池大小的關系
- Java四種線程池的使用
- 深入理解Java之線程池
- java并發編程III
- Java 8并發工具包漫游指南
- 聊聊并發
- 聊聊并發(一)——深入分析Volatile的實現原理
- 聊聊并發(二)——Java SE1.6中的Synchronized
- 文件
- 網絡
- index
- 內存文章索引
- 基礎文章索引
- 線程文章索引
- 網絡文章索引
- IOC
- 設計模式文章索引
- 面試
- Java常量池詳解之一道比較蛋疼的面試題
- 近5年133個Java面試問題列表
- Java工程師成神之路
- Java字符串問題Top10
- 設計模式
- Java:單例模式的七種寫法
- Java 利用枚舉實現單例模式
- 常用jar
- HttpClient和HtmlUnit的比較總結
- IO
- NIO
- NIO入門
- 注解
- Java Annotation認知(包括框架圖、詳細介紹、示例說明)