作者 Java團長關(guān)注2017.02.10 10:50* 字數(shù) 14233 閱讀 3176評論 18喜歡 273Java 面試隨著時間的改變而改變。在過去的日子里,當你知道 String 和 StringBuilder 的區(qū)別就能讓你直接進入第二輪面試,但是現(xiàn)在問題變得越來越高級,面試官問的問題也更深入。 在我初入職場的時候,類似于 Vector 與 Array 的區(qū)別、HashMap 與 Hashtable 的區(qū)別是最流行的問題,只需要記住它們,就能在面試中獲得更好的機會,但這種情形已經(jīng)不復(fù)存在。如今,你將會被問到許多 Java 程序員都沒有看過的領(lǐng)域,如 NIO,設(shè)計模式,成熟的單元測試,或者那些很難掌握的知識,如并發(fā)、算法、數(shù)據(jù)結(jié)構(gòu)及編碼。
由于我喜歡研究面試題,因此我已經(jīng)收集了許多的面試問題,包括許多許多不同的主題。我已經(jīng)為這眾多的問題準備一段時間了,現(xiàn)在我將它們分享給你們。這里面不但包含經(jīng)典的面試問題,如線程、集合、equals 和 hashcode、socket,而且還包含了 NIO、數(shù)組、字符串、Java 8 等主題。
該列表包含了入門級 Java 程序員和多年經(jīng)驗的高級開發(fā)者的問題。無論你是 1、2、3、4、5、6、7、8、9 還是 10 年經(jīng)驗的開發(fā)者,你都能在其中找到一些有趣的問題。這里包含了一些超級容易回答的問題,同時包含經(jīng)驗豐富的 Java 程序員也會棘手的問題。
當然你們也是非常幸運的,當今有許多好的書來幫助你準備 Java 面試,其中有一本我覺得特別有用和有趣的是 Markham 的 Java 程序面試揭秘(Java PRogramming Interview Exposed)。 這本書會告訴你一些 Java 和 JEE 面試中最重要的主題,即使你不是準備 Java 面試,也值得一讀。
該問題列表特別長,我們有各個地方的問題,所以,答案必須要短小、簡潔、干脆,不拖泥帶水。因此,除了這一個段落,你只會聽到問題與答案,再無其他內(nèi)容,沒有反饋,也沒有評價。為此,我已經(jīng)寫好了一些博文,在這些文章中你可以找到我對某些問題的觀點,如我為什么喜歡這個問題,這個問題的挑戰(zhàn)是什么?期望從面試者那獲取到什么樣的答案?
這個列表有一點不同,我鼓勵你采用類似的方式去分享問題和答案,這樣容易溫習(xí)。我希望這個列表對面試官和候選人都有很好的用處,面試官可以對這些問題上做一些改變以獲取新奇和令人驚奇的元素,這對一次好的面試來說非常重要。而候選者,可以擴展和測試 Java 程序語言和平臺關(guān)鍵領(lǐng)域的知識。2015 年,會更多的關(guān)注并發(fā)概念,JVM 內(nèi)部,32 位 JVM 和 64 JVM的區(qū)別,單元測試及整潔的代碼。我確信,如果你讀過這個龐大的 Java 面試問題列表,無論是電話面試還是面對面的面試,你都能有很好的表現(xiàn)。
Java 面試中的重要話題
除了你看到的驚人的問題數(shù)量,我也盡量保證質(zhì)量。我不止一次分享各個重要主題中的問題,也確保包含所謂的高級話題,這些話題很多程序員不喜歡準備或者直接放棄,因為他們的工作不會涉及到這些。Java NIO 和 JVM 底層就是最好的例子。你也可以將設(shè)計模式劃分到這一類中,但是越來越多有經(jīng)驗的程序員了解 GOF 設(shè)計模式并應(yīng)用這些模式。我也盡量在這個列表中包含 2015 年最新的面試問題,這些問題可能是來年關(guān)注的核心。為了給你一個大致的了解,下面列出這份 Java 面試問題列表包含的主題:
多線程,并發(fā)及線程基礎(chǔ)數(shù)據(jù)類型轉(zhuǎn)換的基本原則垃圾回收(GC)Java 集合框架數(shù)組字符串GOF 設(shè)計模式SOLID (單一功能、開閉原則、里氏替換、接口隔離以及依賴反轉(zhuǎn))設(shè)計原則抽象類與接口Java 基礎(chǔ),如 equals 和 hashcode泛型與枚舉Java IO 與 NIO常用網(wǎng)絡(luò)協(xié)議Java 中的數(shù)據(jù)結(jié)構(gòu)和算法正則表達式JVM 底層Java 最佳實踐JDBCDate, Time 與 CalendarJava 處理 xmlJUnit編程
120 大 Java 面試題及答案
現(xiàn)在是時候給你展示我近 5 年從各種面試中收集來的 120 個問題了。我確定你在自己的面試中見過很多這些問題,很多問題你也能正確回答。
多線程、并發(fā)及線程的基礎(chǔ)問題
1)Java 中能創(chuàng)建 Volatile 數(shù)組嗎?能,Java 中可以創(chuàng)建 volatile 類型數(shù)組,不過只是一個指向數(shù)組的引用,而不是整個數(shù)組。我的意思是,如果改變引用指向的數(shù)組,將會受到 volatile 的保護,但是如果多個線程同時改變數(shù)組的元素,volatile 標示符就不能起到之前的保護作用了。
2)volatile 能使得一個非原子操作變成原子操作嗎?一個典型的例子是在類中有一個 long 類型的成員變量。如果你知道該成員變量會被多個線程訪問,如計數(shù)器、價格等,你最好是將其設(shè)置為 volatile。為什么?因為 Java 中讀取 long 類型變量不是原子的,需要分成兩步,如果一個線程正在修改該 long 變量的值,另一個線程可能只能看到該值的一半(前 32 位)。但是對一個 volatile 型的 long 或 double 變量的讀寫是原子。
3)volatile 修飾符的有過什么實踐?一種實踐是用 volatile 修飾 long 和 double 變量,使其能按原子類型來讀寫。double 和 long 都是64位寬,因此對這兩種類型的讀是分為兩部分的,第一次讀取第一個 32 位,然后再讀剩下的 32 位,這個過程不是原子的,但 Java 中 volatile 型的 long 或 double 變量的讀寫是原子的。volatile 修復(fù)符的另一個作用是提供內(nèi)存屏障(memory barrier),例如在分布式框架中的應(yīng)用。簡單的說,就是當你寫一個 volatile 變量之前,Java 內(nèi)存模型會插入一個寫屏障(write barrier),讀一個 volatile 變量之前,會插入一個讀屏障(read barrier)。意思就是說,在你寫一個 volatile 域時,能保證任何線程都能看到你寫的值,同時,在寫之前,也能保證任何數(shù)值的更新對所有線程是可見的,因為內(nèi)存屏障會將其他所有寫的值更新到緩存。
4)volatile 類型變量提供什么保證?(答案)volatile 變量提供順序和可見性保證,例如,JVM 或者 JIT為了獲得更好的性能會對語句重排序,但是 volatile 類型變量即使在沒有同步塊的情況下賦值也不會與其他語句重排序。 volatile 提供 happens-before 的保證,確保一個線程的修改能對其他線程是可見的。某些情況下,volatile 還能提供原子性,如讀 64 位數(shù)據(jù)類型,像 long 和 double 都不是原子的,但 volatile 類型的 double 和 long 就是原子的。
5) 10 個線程和 2 個線程的同步代碼,哪個更容易寫?從寫代碼的角度來說,兩者的復(fù)雜度是相同的,因為同步代碼與線程數(shù)量是相互獨立的。但是同步策略的選擇依賴于線程的數(shù)量,因為越多的線程意味著更大的競爭,所以你需要利用同步技術(shù),如鎖分離,這要求更復(fù)雜的代碼和專業(yè)知識。
6)你是如何調(diào)用 wait()方法的?使用 if 塊還是循環(huán)?為什么?(答案)wait() 方法應(yīng)該在循環(huán)調(diào)用,因為當線程獲取到 CPU 開始執(zhí)行的時候,其他條件可能還沒有滿足,所以在處理前,循環(huán)檢測條件是否滿足會更好。下面是一段標準的使用 wait 和 notify 方法的代碼:
// The standard idiom for using the wait methodsynchronized (obj) {while (condition does not hold)obj.wait(); // (Releases lock, and reacquires on wakeup)... // Perform action appropriate to condition}參見 Effective Java 第 69 條,獲取更多關(guān)于為什么應(yīng)該在循環(huán)中來調(diào)用 wait 方法的內(nèi)容。
7)什么是多線程環(huán)境下的偽共享(false sharing)?偽共享是多線程系統(tǒng)(每個處理器有自己的局部緩存)中一個眾所周知的性能問題。偽共享發(fā)生在不同處理器的上的線程對變量的修改依賴于相同的緩存行,如下圖所示:
偽共享有經(jīng)驗程序員的 Java 面試題
偽共享問題很難被發(fā)現(xiàn),因為線程可能訪問完全不同的全局變量,內(nèi)存中卻碰巧在很相近的位置上。如其他諸多的并發(fā)問題,避免偽共享的最基本方式是仔細審查代碼,根據(jù)緩存行來調(diào)整你的數(shù)據(jù)結(jié)構(gòu)。
8)什么是 Busy spin?我們?yōu)槭裁匆褂盟緽usy spin 是一種在不釋放 CPU 的基礎(chǔ)上等待事件的技術(shù)。它經(jīng)常用于避免丟失 CPU 緩存中的數(shù)據(jù)(如果線程先暫停,之后在其他CPU上運行就會丟失)。所以,如果你的工作要求低延遲,并且你的線程目前沒有任何順序,這樣你就可以通過循環(huán)檢測隊列中的新消息來代替調(diào)用 sleep() 或 wait() 方法。它唯一的好處就是你只需等待很短的時間,如幾微秒或幾納秒。LMAX 分布式框架是一個高性能線程間通信的庫,該庫有一個 BusySpinWaitStrategy 類就是基于這個概念實現(xiàn)的,使用 busy spin 循環(huán) EventProcessors 等待屏障。
9)Java 中怎么獲取一份線程 dump 文件?在 linux 下,你可以通過命令 kill -3 PID (Java 進程的進程 ID)來獲取 Java 應(yīng)用的 dump 文件。在 Windows 下,你可以按下 Ctrl + Break 來獲取。這樣 JVM 就會將線程的 dump 文件打印到標準輸出或錯誤文件中,它可能打印在控制臺或者日志文件中,具體位置依賴應(yīng)用的配置。如果你使用Tomcat。
10)Swing 是線程安全的?(答案)不是,Swing 不是線程安全的。你不能通過任何線程來更新 Swing 組件,如 JTable、JList 或 JPanel,事實上,它們只能通過 GUI 或 AWT 線程來更新。這就是為什么 Swing 提供 invokeAndWait() 和 invokeLater() 方法來獲取其他線程的 GUI 更新請求。這些方法將更新請求放入 AWT 的線程隊列中,可以一直等待,也可以通過異步更新直接返回結(jié)果。你也可以在參考答案中查看和學(xué)習(xí)到更詳細的內(nèi)容。
11)什么是線程局部變量?(答案)線程局部變量是局限于線程內(nèi)部的變量,屬于線程自身所有,不在多個線程間共享。Java 提供 ThreadLocal 類來支持線程局部變量,是一種實現(xiàn)線程安全的方式。但是在管理環(huán)境下(如 web 服務(wù)器)使用線程局部變量的時候要特別小心,在這種情況下,工作線程的生命周期比任何應(yīng)用變量的生命周期都要長。任何線程局部變量一旦在工作完成后沒有釋放,Java 應(yīng)用就存在內(nèi)存泄露的風險。
12)用 wait-notify 寫一段代碼來解決生產(chǎn)者-消費者問題?(答案)請參考答案中的示例代碼。只要記住在同步塊中調(diào)用 wait() 和 notify()方法,如果阻塞,通過循環(huán)來測試等待條件。
13) 用 Java 寫一個線程安全的單例模式(Singleton)?(答案)請參考答案中的示例代碼,這里面一步一步教你創(chuàng)建一個線程安全的 Java 單例類。當我們說線程安全時,意思是即使初始化是在多線程環(huán)境中,仍然能保證單個實例。Java 中,使用枚舉作為單例類是最簡單的方式來創(chuàng)建線程安全單例模式的方式。
14)Java 中 sleep 方法和 wait 方法的區(qū)別?(答案)雖然兩者都是用來暫停當前運行的線程,但是 sleep() 實際上只是短暫停頓,因為它不會釋放鎖,而 wait() 意味著條件等待,這就是為什么該方法要釋放鎖,因為只有這樣,其他等待的線程才能在滿足條件時獲取到該鎖。
15)什么是不可變對象(immutable object)?Java 中怎么創(chuàng)建一個不可變對象?(答案)不可變對象指對象一旦被創(chuàng)建,狀態(tài)就不能再改變。任何修改都會創(chuàng)建一個新的對象,如 String、Integer及其它包裝類。詳情參見答案,一步一步指導(dǎo)你在 Java 中創(chuàng)建一個不可變的類。
16)我們能創(chuàng)建一個包含可變對象的不可變對象嗎?是的,我們是可以創(chuàng)建一個包含可變對象的不可變對象的,你只需要謹慎一點,不要共享可變對象的引用就可以了,如果需要變化時,就返回原對象的一個拷貝。最常見的例子就是對象中包含一個日期對象的引用。
數(shù)據(jù)類型和 Java 基礎(chǔ)面試問題
17)Java 中應(yīng)該使用什么數(shù)據(jù)類型來代表價格?(答案)如果不是特別關(guān)心內(nèi)存和性能的話,使用BigDecimal,否則使用預(yù)定義精度的 double 類型。
18)怎么將 byte 轉(zhuǎn)換為 String?(答案)可以使用 String 接收 byte[] 參數(shù)的構(gòu)造器來進行轉(zhuǎn)換,需要注意的點是要使用的正確的編碼,否則會使用平臺默認編碼,這個編碼可能跟原來的編碼相同,也可能不同。
19)Java 中怎樣將 bytes 轉(zhuǎn)換為 long 類型?這個問題你來回答 :-)20)我們能將 int 強制轉(zhuǎn)換為 byte 類型的變量嗎?如果該值大于 byte 類型的范圍,將會出現(xiàn)什么現(xiàn)象?是的,我們可以做強制轉(zhuǎn)換,但是 Java 中 int 是 32 位的,而 byte 是 8 位的,所以,如果強制轉(zhuǎn)化是,int 類型的高 24 位將會被丟棄,byte 類型的范圍是從 -128 到 128。
21)存在兩個類,B 繼承 A,C 繼承 B,我們能將 B 轉(zhuǎn)換為 C 么?如 C = (C) B;(answer答案)
22)哪個類包含 clone 方法?是 Cloneable 還是 Object?(答案)java.lang.Cloneable 是一個標示性接口,不包含任何方法,clone 方法在 object 類中定義。并且需要知道 clone() 方法是一個本地方法,這意味著它是由 c 或 c++ 或 其他本地語言實現(xiàn)的。
23)Java 中 ++ 操作符是線程安全的嗎?(答案)23)不是線程安全的操作。它涉及到多個指令,如讀取變量值,增加,然后存儲回內(nèi)存,這個過程可能會出現(xiàn)多個線程交差。
24)a = a + b 與 a += b 的區(qū)別(答案)+= 隱式的將加操作的結(jié)果類型強制轉(zhuǎn)換為持有結(jié)果的類型。如果兩這個整型相加,如 byte、short 或者 int,首先會將它們提升到 int 類型,然后在執(zhí)行加法操作。如果加法操作的結(jié)果比 a 的最大值要大,則 a+b 會出現(xiàn)編譯錯誤,但是 a += b 沒問題,如下:byte a = 127;byte b = 127;b = a + b; // error : cannot convert from int to byteb += a; // ok(譯者注:這個地方應(yīng)該表述的有誤,其實無論 a+b 的值為多少,編譯器都會報錯,因為 a+b 操作會將 a、b 提升為 int 類型,所以將 int 類型賦值給 byte 就會編譯出錯)
25)我能在不進行強制轉(zhuǎn)換的情況下將一個 double 值賦值給 long 類型的變量嗎?(答案)不行,你不能在沒有強制類型轉(zhuǎn)換的前提下將一個 double 值賦值給 long 類型的變量,因為 double 類型的范圍比 long 類型更廣,所以必須要進行強制轉(zhuǎn)換。
26)3*0.1 == 0.3 將會返回什么?true 還是 false?(答案)false,因為有些浮點數(shù)不能完全精確的表示出來。
27)int 和 Integer 哪個會占用更多的內(nèi)存?(答案)Integer 對象會占用更多的內(nèi)存。Integer 是一個對象,需要存儲對象的元數(shù)據(jù)。但是 int 是一個原始類型的數(shù)據(jù),所以占用的空間更少。
28)為什么 Java 中的 String 是不可變的(Immutable)?(answer答案)Java 中的 String 不可變是因為 Java 的設(shè)計者認為字符串使用非常頻繁,將字符串設(shè)置為不可變可以允許多個客戶端之間共享相同的字符串。更詳細的內(nèi)容參見答案。
29)我們能在 Switch 中使用 String 嗎?(answer答案)從 Java 7 開始,我們可以在 switch case 中使用字符串,但這僅僅是一個語法糖。內(nèi)部實現(xiàn)在 switch 中使用字符串的 hash code。
30)Java 中的構(gòu)造器鏈是什么?(answer答案)當你從一個構(gòu)造器中調(diào)用另一個構(gòu)造器,就是Java 中的構(gòu)造器鏈。這種情況只在重載了類的構(gòu)造器的時候才會出現(xiàn)。
JVM 底層 與 GC(Garbage Collection) 的面試問題
31)64 位 JVM 中,int 的長度是多數(shù)?Java 中,int 類型變量的長度是一個固定值,與平臺無關(guān),都是 32 位。意思就是說,在 32 位 和 64 位 的Java 虛擬機中,int 類型的長度是相同的。
32)Serial 與 Parallel GC之間的不同之處?(答案)Serial 與 Parallel 在GC執(zhí)行的時候都會引起 stop-the-world。它們之間主要不同 serial 收集器是默認的復(fù)制收集器,執(zhí)行 GC 的時候只有一個線程,而 parallel 收集器使用多個 GC 線程來執(zhí)行。
33)32 位和 64 位的 JVM,int 類型變量的長度是多數(shù)?(答案)32 位和 64 位的 JVM 中,int 類型變量的長度是相同的,都是 32 位或者 4 個字節(jié)。
34)Java 中 WeakReference 與 SoftReference的區(qū)別?(答案)雖然 WeakReference 與 SoftReference 都有利于提高 GC 和 內(nèi)存的效率,但是 WeakReference ,一旦失去最后一個強引用,就會被 GC 回收,而軟引用雖然不能阻止被回收,但是可以延遲到 JVM 內(nèi)存不足的時候。
35)WeakHashMap 是怎么工作的?(答案)WeakHashMap 的工作與正常的 HashMap 類似,但是使用弱引用作為 key,意思就是當 key 對象沒有任何引用時,key/value 將會被回收。
36)JVM 選項 -XX:+UseCompressedOops 有什么作用?為什么要使用?(答案)當你將你的應(yīng)用從 32 位的 JVM 遷移到 64 位的 JVM 時,由于對象的指針從 32 位增加到了 64 位,因此堆內(nèi)存會突然增加,差不多要翻倍。這也會對 CPU 緩存(容量比內(nèi)存小很多)的數(shù)據(jù)產(chǎn)生不利的影響。因為,遷移到 64 位的 JVM 主要動機在于可以指定最大堆大小,通過壓縮 OOP 可以節(jié)省一定的內(nèi)存。通過 -XX:+UseCompressedOops 選項,JVM 會使用 32 位的 OOP,而不是 64 位的 OOP。
37)怎樣通過 Java 程序來判斷 JVM 是 32 位 還是 64 位?(答案)你可以檢查某些系統(tǒng)屬性如 sun.arch.data.model 或 os.arch 來獲取該信息。
38)32 位 JVM 和 64 位 JVM 的最大堆內(nèi)存分別是多數(shù)?(答案)理論上說上 32 位的 JVM 堆內(nèi)存可以到達 2^32,即 4GB,但實際上會比這個小很多。不同操作系統(tǒng)之間不同,如 Windows 系統(tǒng)大約 1.5 GB,Solaris 大約 3GB。64 位 JVM允許指定最大的堆內(nèi)存,理論上可以達到 2^64,這是一個非常大的數(shù)字,實際上你可以指定堆內(nèi)存大小到 100GB。甚至有的 JVM,如 Azul,堆內(nèi)存到 1000G 都是可能的。
39)JRE、JDK、JVM 及 JIT 之間有什么不同?(答案)JRE 代表 Java 運行時(Java run-time),是運行 Java 引用所必須的。JDK 代表 Java 開發(fā)工具(Java development kit),是 Java 程序的開發(fā)工具,如 Java 編譯器,它也包含 JRE。JVM 代表 Java 虛擬機(Java virtual machine),它的責任是運行 Java 應(yīng)用。JIT 代表即時編譯(Just In Time compilation),當代碼執(zhí)行的次數(shù)超過一定的閾值時,會將 Java 字節(jié)碼轉(zhuǎn)換為本地代碼,如,主要的熱點代碼會被準換為本地代碼,這樣有利大幅度提高 Java 應(yīng)用的性能。最近5年133個Java面試問題列表
3 年工作經(jīng)驗的 Java 面試題
40)解釋 Java 堆空間及 GC?(答案)當通過 Java 命令啟動 Java 進程的時候,會為它分配內(nèi)存。內(nèi)存的一部分用于創(chuàng)建堆空間,當程序中創(chuàng)建對象的時候,就從對空間中分配內(nèi)存。GC 是 JVM 內(nèi)部的一個進程,回收無效對象的內(nèi)存用于將來的分配。最近5年133個Java面試問題列表
JVM 底層面試題及答案
41)你能保證 GC 執(zhí)行嗎?(答案)不能,雖然你可以調(diào)用 System.gc() 或者 Runtime.gc(),但是沒有辦法保證 GC 的執(zhí)行。
42)怎么獲取 Java 程序使用的內(nèi)存?堆使用的百分比?可以通過 java.lang.Runtime 類中與內(nèi)存相關(guān)方法來獲取剩余的內(nèi)存,總內(nèi)存及最大堆內(nèi)存。通過這些方法你也可以獲取到堆使用的百分比及堆內(nèi)存的剩余空間。Runtime.freeMemory() 方法返回剩余空間的字節(jié)數(shù),Runtime.totalMemory() 方法總內(nèi)存的字節(jié)數(shù),Runtime.maxMemory() 返回最大內(nèi)存的字節(jié)數(shù)。
43)Java 中堆和棧有什么區(qū)別?(答案)JVM 中堆和棧屬于不同的內(nèi)存區(qū)域,使用目的也不同。棧常用于保存方法幀和局部變量,而對象總是在堆上分配。棧通常都比堆小,也不會在多個線程之間共享,而堆被整個 JVM 的所有線程共享。
最近5年133個Java面試問題列表
關(guān)于內(nèi)存的的面試問題和答案
Java 基本概念面試題
44)“a==b”和”a.equals(b)”有什么區(qū)別?(答案)如果 a 和 b 都是對象,則 a==b 是比較兩個對象的引用,只有當 a 和 b 指向的是堆中的同一個對象才會返回 true,而 a.equals(b) 是進行邏輯比較,所以通常需要重寫該方法來提供邏輯一致性的比較。例如,String 類重寫 equals() 方法,所以可以用于兩個不同對象,但是包含的字母相同的比較。
45)a.hashCode() 有什么用?與 a.equals(b) 有什么關(guān)系?(答案)hashCode() 方法是相應(yīng)對象整型的 hash 值。它常用于基于 hash 的集合類,如 Hashtable、HashMap、LinkedHashMap等等。它與 equals() 方法關(guān)系特別緊密。根據(jù) Java 規(guī)范,兩個使用 equal() 方法來判斷相等的對象,必須具有相同的 hash code。
46)final、finalize 和 finally 的不同之處?(答案)final 是一個修飾符,可以修飾變量、方法和類。如果 final 修飾變量,意味著該變量的值在初始化后不能被改變。finalize 方法是在對象被回收之前調(diào)用的方法,給對象自己最后一個復(fù)活的機會,但是什么時候調(diào)用 finalize 沒有保證。finally 是一個關(guān)鍵字,與 try 和 catch 一起用于異常的處理。finally 塊一定會被執(zhí)行,無論在 try 塊中是否有發(fā)生異常。
47)Java 中的編譯期常量是什么?使用它又什么風險?公共靜態(tài)不可變(public static final )變量也就是我們所說的編譯期常量,這里的 public 可選的。實際上這些變量在編譯時會被替換掉,因為編譯器知道這些變量的值,并且知道這些變量在運行時不能改變。這種方式存在的一個問題是你使用了一個內(nèi)部的或第三方庫中的公有編譯時常量,但是這個值后面被其他人改變了,但是你的客戶端仍然在使用老的值,甚至你已經(jīng)部署了一個新的jar。為了避免這種情況,當你在更新依賴 JAR 文件時,確保重新編譯你的程序。
Java 集合框架的面試題
這部分也包含數(shù)據(jù)結(jié)構(gòu)、算法及數(shù)組的面試問題
48) List、Set、Map 和 Queue 之間的區(qū)別(答案)List 是一個有序集合,允許元素重復(fù)。它的某些實現(xiàn)可以提供基于下標值的常量訪問時間,但是這不是 List 接口保證的。Set 是一個無序集合。
49)poll() 方法和 remove() 方法的區(qū)別?poll() 和 remove() 都是從隊列中取出一個元素,但是 poll() 在獲取元素失敗的時候會返回空,但是 remove() 失敗的時候會拋出異常。
50)Java 中 LinkedHashMap 和 PriorityQueue 的區(qū)別是什么?(答案)PriorityQueue 保證最高或者最低優(yōu)先級的的元素總是在隊列頭部,但是 LinkedHashMap 維持的順序是元素插入的順序。當遍歷一個 PriorityQueue 時,沒有任何順序保證,但是 LinkedHashMap 課保證遍歷順序是元素插入的順序。
51)ArrayList 與 LinkedList 的不區(qū)別?(答案)最明顯的區(qū)別是 ArrrayList 底層的數(shù)據(jù)結(jié)構(gòu)是數(shù)組,支持隨機訪問,而 LinkedList 的底層數(shù)據(jù)結(jié)構(gòu)書鏈表,不支持隨機訪問。使用下標訪問一個元素,ArrayList 的時間復(fù)雜度是 O(1),而 LinkedList 是 O(n)。更多細節(jié)的討論參見答案。
52)用哪兩種方式來實現(xiàn)集合的排序?(答案)你可以使用有序集合,如 TreeSet 或 TreeMap,你也可以使用有順序的的集合,如 list,然后通過 Collections.sort() 來排序。
53)Java 中怎么打印數(shù)組?(answer答案)你可以使用 Arrays.toString() 和 Arrays.deepToString() 方法來打印數(shù)組。由于數(shù)組沒有實現(xiàn) toString() 方法,所以如果將數(shù)組傳遞給 System.out.println() 方法,將無法打印出數(shù)組的內(nèi)容,但是 Arrays.toString() 可以打印每個元素。
54)Java 中的 LinkedList 是單向鏈表還是雙向鏈表?(答案)是雙向鏈表,你可以檢查 JDK 的源碼。在 Eclipse,你可以使用快捷鍵 Ctrl + T,直接在編輯器中打開該類。
55)Java 中的 TreeMap 是采用什么樹實現(xiàn)的?(答案)Java 中的 TreeMap 是使用紅黑樹實現(xiàn)的。
56) Hashtable 與 HashMap 有什么不同之處?(答案)這兩個類有許多不同的地方,下面列出了一部分:a) Hashtable 是 JDK 1 遺留下來的類,而 HashMap 是后來增加的。b)Hashtable 是同步的,比較慢,但 HashMap 沒有同步策略,所以會更快。c)Hashtable 不允許有個空的 key,但是 HashMap 允許出現(xiàn)一個 null key。更多的不同之處參見答案。
57)Java 中的 HashSet,內(nèi)部是如何工作的?(answer答案)HashSet 的內(nèi)部采用 HashMap來實現(xiàn)。由于 Map 需要 key 和 value,所以所有 key 的都有一個默認 value。類似于 HashMap,HashSet 不允許重復(fù)的 key,只允許有一個null key,意思就是 HashSet 中只允許存儲一個 null 對象。
58)寫一段代碼在遍歷 ArrayList 時移除一個元素?(答案)該問題的關(guān)鍵在于面試者使用的是 ArrayList 的 remove() 還是 Iterator 的 remove()方法。這有一段示例代碼,是使用正確的方式來實現(xiàn)在遍歷的過程中移除元素,而不會出現(xiàn) ConcurrentModificationException 異常的示例代碼。
59)我們能自己寫一個容器類,然后使用 for-each 循環(huán)碼?可以,你可以寫一個自己的容器類。如果你想使用 Java 中增強的循環(huán)來遍歷,你只需要實現(xiàn) Iterable 接口。如果你實現(xiàn) Collection 接口,默認就具有該屬性。
60)ArrayList 和 HashMap 的默認大小是多數(shù)?(答案)
在 Java 7 中,ArrayList 的默認大小是 10 個元素,HashMap 的默認大小是16個元素(必須是2的冪)。這就是 Java 7 中 ArrayList 和 HashMap 類的代碼片段:
// from ArrayList.java JDK 1.7private static final int DEFAULT_CAPACITY = 10;
//from HashMap.java JDK 7static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 1661)有沒有可能兩個不相等的對象有有相同的 hashcode?有可能,兩個不相等的對象可能會有相同的 hashcode 值,這就是為什么在 hashmap 中會有沖突。相等 hashcode 值的規(guī)定只是說如果兩個對象相等,必須有相同的hashcode 值,但是沒有關(guān)于不相等對象的任何規(guī)定。
62)兩個相同的對象會有不同的的 hash code 嗎?不能,根據(jù) hash code 的規(guī)定,這是不可能的。
63)我們可以在 hashcode() 中使用隨機數(shù)字嗎?(答案)不行,因為對象的 hashcode 值必須是相同的。參見答案獲取更多關(guān)于 Java 中重寫 hashCode() 方法的知識。
64)Java 中,Comparator 與 Comparable 有什么不同?(答案)Comparable 接口用于定義對象的自然順序,而 comparator 通常用于定義用戶定制的順序。Comparable 總是只有一個,但是可以有多個 comparator 來定義對象的順序。
65)為什么在重寫 equals 方法的時候需要重寫 hashCode 方法?(答案)因為有強制的規(guī)范指定需要同時重寫 hashcode 與 equal 是方法,許多容器類,如 HashMap、HashSet 都依賴于 hashcode 與 equals 的規(guī)定。
Java IO 和 NIO 的面試題
IO 是 Java 面試中一個非常重要的點。你應(yīng)該很好掌握 Java IO,NIO,NIO2 以及與操作系統(tǒng),磁盤 IO 相關(guān)的基礎(chǔ)知識。下面是 Java IO 中經(jīng)常問的問題。
66)在我 Java 程序中,我有三個 socket,我需要多少個線程來處理?
67)Java 中怎么創(chuàng)建 ByteBuffer?
68)Java 中,怎么讀寫 ByteBuffer ?
69)Java 采用的是大端還是小端?
70)ByteBuffer 中的字節(jié)序是什么?
71)Java 中,直接緩沖區(qū)與非直接緩沖器有什么區(qū)別?(答案)
72)Java 中的內(nèi)存映射緩存區(qū)是什么?(answer答案)
73)socket 選項 TCP NO DELAY 是指什么?
74)TCP 協(xié)議與 UDP 協(xié)議有什么區(qū)別?(answer答案)
75)Java 中,ByteBuffer 與 StringBuffer有什么區(qū)別?(答案)
Java 最佳實踐的面試問題
包含 Java 中各個部分的最佳實踐,如集合,字符串,IO,多線程,錯誤和異常處理,設(shè)計模式等等。
76)Java 中,編寫多線程程序的時候你會遵循哪些最佳實踐?(答案)這是我在寫Java 并發(fā)程序的時候遵循的一些最佳實踐:a)給線程命名,這樣可以幫助調(diào)試。b)最小化同步的范圍,而不是將整個方法同步,只對關(guān)鍵部分做同步。c)如果可以,更偏向于使用 volatile 而不是 synchronized。d)使用更高層次的并發(fā)工具,而不是使用 wait() 和 notify() 來實現(xiàn)線程間通信,如 BlockingQueue,CountDownLatch 及 Semeaphore。e)優(yōu)先使用并發(fā)集合,而不是對集合進行同步。并發(fā)集合提供更好的可擴展性。
77)說出幾點 Java 中使用 Collections 的最佳實踐(答案)這是我在使用 Java 中 Collectionc 類的一些最佳實踐:a)使用正確的集合類,例如,如果不需要同步列表,使用 ArrayList 而不是 Vector。b)優(yōu)先使用并發(fā)集合,而不是對集合進行同步。并發(fā)集合提供更好的可擴展性。c)使用接口代表和訪問集合,如使用List存儲 ArrayList,使用 Map 存儲 HashMap 等等。d)使用迭代器來循環(huán)集合。e)使用集合的時候使用泛型。
78)說出至少 5 點在 Java 中使用線程的最佳實踐。(答案)這個問題與之前的問題類似,你可以使用上面的答案。對線程來說,你應(yīng)該:a)對線程命名b)將線程和任務(wù)分離,使用線程池執(zhí)行器來執(zhí)行 Runnable 或 Callable。c)使用線程池
79)說出 5 條 IO 的最佳實踐(答案)IO 對 Java 應(yīng)用的性能非常重要。理想情況下,你不應(yīng)該在你應(yīng)用的關(guān)鍵路徑上避免 IO 操作。下面是一些你應(yīng)該遵循的 Java IO 最佳實踐:a)使用有緩沖區(qū)的 IO 類,而不要單獨讀取字節(jié)或字符。b)使用 NIO 和 NIO2c)在 finally 塊中關(guān)閉流,或者使用 try-with-resource 語句。d)使用內(nèi)存映射文件獲取更快的 IO。
80)列出 5 個應(yīng)該遵循的 JDBC 最佳實踐(答案)有很多的最佳實踐,你可以根據(jù)你的喜好來例舉。下面是一些更通用的原則:a)使用批量的操作來插入和更新數(shù)據(jù)b)使用 PreparedStatement 來避免 SQL 異常,并提高性能。c)使用數(shù)據(jù)庫連接池d)通過列名來獲取結(jié)果集,不要使用列的下標來獲取。
81)說出幾條 Java 中方法重載的最佳實踐?(答案)下面有幾條可以遵循的方法重載的最佳實踐來避免造成自動裝箱的混亂。a)不要重載這樣的方法:一個方法接收 int 參數(shù),而另個方法接收 Integer 參數(shù)。b)不要重載參數(shù)數(shù)量一致,而只是參數(shù)順序不同的方法。c)如果重載的方法參數(shù)個數(shù)多于 5 個,采用可變參數(shù)。
Date、Time 及 Calendar 的面試題
82)在多線程環(huán)境下,SimpleDateFormat 是線程安全的嗎?(答案)不是,非常不幸,DateFormat 的所有實現(xiàn),包括 SimpleDateFormat 都不是線程安全的,因此你不應(yīng)該在多線程序中使用,除非是在對外線程安全的環(huán)境中使用,如 將 SimpleDateFormat 限制在 ThreadLocal 中。如果你不這么做,在解析或者格式化日期的時候,可能會獲取到一個不正確的結(jié)果。因此,從日期、時間處理的所有實踐來說,我強力推薦 joda-time 庫。
83)Java 中如何格式化一個日期?如格式化為 ddMMyyyy 的形式?(答案)Java 中,可以使用 SimpleDateFormat 類或者 joda-time 庫來格式日期。DateFormat 類允許你使用多種流行的格式來格式化日期。參見答案中的示例代碼,代碼中演示了將日期格式化成不同的格式,如 dd-MM-yyyy 或 ddMMyyyy。
84)Java 中,怎么在格式化的日期中顯示時區(qū)?(答案)
85)Java 中 java.util.Date 與 java.sql.Date 有什么區(qū)別?(答案)
86)Java 中,如何計算兩個日期之間的差距?(程序)
87)Java 中,如何將字符串 YYYYMMDD 轉(zhuǎn)換為日期?(答案)
單元測試 JUnit 面試題
89)如何測試靜態(tài)方法?(答案)可以使用 PowerMock 庫來測試靜態(tài)方法。
90)怎么利用 JUnit 來測試一個方法的異常?(答案)
91)你使用過哪個單元測試庫來測試你的 Java 程序?(答案)
92)@Before 和 @BeforeClass 有什么區(qū)別?(答案)
編程和代碼相關(guān)的面試題
93)怎么檢查一個字符串只包含數(shù)字?(解決方案)
94)Java 中如何利用泛型寫一個 LRU 緩存?(答案<)
95)寫一段 Java 程序?qū)?byte 轉(zhuǎn)換為 long?(答案)
95)在不使用 StringBuffer 的前提下,怎么反轉(zhuǎn)一個字符串?(解決方案)
97)Java 中,怎么獲取一個文件中單詞出現(xiàn)的最高頻率?(解決方案)
98)如何檢查出兩個給定的字符串是反序的?(解決方案)
99)Java 中,怎么打印出一個字符串的所有排列?(解決方案)
100)Java 中,怎樣才能打印出數(shù)組中的重復(fù)元素?(解決方案)
101)Java 中如何將字符串轉(zhuǎn)換為整數(shù)?(解決方案)
102)在沒有使用臨時變量的情況如何交換兩個整數(shù)變量的值?(解決方案)
關(guān)于 OOP 和設(shè)計模式的面試題
這部分包含 Java 面試過程中關(guān)于 SOLID 的設(shè)計原則,OOP 基礎(chǔ),如類,對象,接口,繼承,多態(tài),封裝,抽象以及更高級的一些概念,如組合、聚合及關(guān)聯(lián)。也包含了 GOF 設(shè)計模式的問題。
103)接口是什么?為什么要使用接口而不是直接使用具體類?接口用于定義 API。它定義了類必須得遵循的規(guī)則。同時,它提供了一種抽象,因為客戶端只使用接口,這樣可以有多重實現(xiàn),如 List 接口,你可以使用可隨機訪問的 ArrayList,也可以使用方便插入和刪除的 LinkedList。接口中不允許寫代碼,以此來保證抽象,但是 Java 8 中你可以在接口聲明靜態(tài)的默認方法,這種方法是具體的。
104)Java 中,抽象類與接口之間有什么不同?(答案)Java 中,抽象類和接口有很多不同之處,但是最重要的一個是 Java 中限制一個類只能繼承一個類,但是可以實現(xiàn)多個接口。抽象類可以很好的定義一個家族類的默認行為,而接口能更好的定義類型,有助于后面實現(xiàn)多態(tài)機制。關(guān)于這個問題的討論請查看答案。
105)除了單例模式,你在生產(chǎn)環(huán)境中還用過什么設(shè)計模式?這需要根據(jù)你的經(jīng)驗來回答。一般情況下,你可以說依賴注入,工廠模式,裝飾模式或者觀察者模式,隨意選擇你使用過的一種即可。不過你要準備回答接下的基于你選擇的模式的問題。
106)你能解釋一下里氏替換原則嗎?(答案)
107) 什么情況下會違反迪米特法則?為什么會有這個問題?(答案)迪米特法則建議“只和朋友說話,不要陌生人說話”,以此來減少類之間的耦合。
108)適配器模式是什么?什么時候使用?適配器模式提供對接口的轉(zhuǎn)換。如果你的客戶端使用某些接口,但是你有另外一些接口,你就可以寫一個適配去來連接這些接口。
109)什么是“依賴注入”和“控制反轉(zhuǎn)”?為什么有人使用?(答案)
110)抽象類是什么?它與接口有什么區(qū)別?你為什么要使用過抽象類?(答案)
111)構(gòu)造器注入和 setter 依賴注入,那種方式更好?(答案)每種方式都有它的缺點和優(yōu)點。構(gòu)造器注入保證所有的注入都被初始化,但是 setter 注入提供更好的靈活性來設(shè)置可選依賴。如果使用 XML 來描述依賴,Setter 注入的可讀寫會更強。經(jīng)驗法則是強制依賴使用構(gòu)造器注入,可選依賴使用 setter 注入。
112)依賴注入和工程模式之間有什么不同?(答案)雖然兩種模式都是將對象的創(chuàng)建從應(yīng)用的邏輯中分離,但是依賴注入比工程模式更清晰。通過依賴注入,你的類就是 POJO,它只知道依賴而不關(guān)心它們怎么獲取。使用工廠模式,你的類需要通過工廠來獲取依賴。因此,使用 DI 會比使用工廠模式更容易測試。關(guān)于這個話題的更詳細討論請參見答案。
113)適配器模式和裝飾器模式有什么區(qū)別?(答案)雖然適配器模式和裝飾器模式的結(jié)構(gòu)類似,但是每種模式的出現(xiàn)意圖不同。適配器模式被用于橋接兩個接口,而裝飾模式的目的是在不修改類的情況下給類增加新的功能。
114)適配器模式和代理模式之前有什么不同?(答案)這個問題與前面的類似,適配器模式和代理模式的區(qū)別在于他們的意圖不同。由于適配器模式和代理模式都是封裝真正執(zhí)行動作的類,因此結(jié)構(gòu)是一致的,但是適配器模式用于接口之間的轉(zhuǎn)換,而代理模式則是增加一個額外的中間層,以便支持分配、控制或智能訪問。
115)什么是模板方法模式?(答案)模板方法提供算法的框架,你可以自己去配置或定義步驟。例如,你可以將排序算法看做是一個模板。它定義了排序的步驟,但是具體的比較,可以使用 Comparable 或者其語言中類似東西,具體策略由你去配置。列出算法概要的方法就是眾所周知的模板方法。
116)什么時候使用訪問者模式?(答案)訪問者模式用于解決在類的繼承層次上增加操作,但是不直接與之關(guān)聯(lián)。這種模式采用雙派發(fā)的形式來增加中間層。
117)什么時候使用組合模式?(答案)組合模式使用樹結(jié)構(gòu)來展示部分與整體繼承關(guān)系。它允許客戶端采用統(tǒng)一的形式來對待單個對象和對象容器。當你想要展示對象這種部分與整體的繼承關(guān)系時采用組合模式。
118)繼承和組合之間有什么不同?(答案)雖然兩種都可以實現(xiàn)代碼復(fù)用,但是組合比繼承共靈活,因為組合允許你在運行時選擇不同的實現(xiàn)。用組合實現(xiàn)的代碼也比繼承測試起來更加簡單。
119)描述 Java 中的重載和重寫?(答案)重載和重寫都允許你用相同的名稱來實現(xiàn)不同的功能,但是重載是編譯時活動,而重寫是運行時活動。你可以在同一個類中重載方法,但是只能在子類中重寫方法。重寫必須要有繼承。
120)Java 中,嵌套公共靜態(tài)類與頂級類有什么不同?(答案)類的內(nèi)部可以有多個嵌套公共靜態(tài)類,但是一個 Java 源文件只能有一個頂級公共類,并且頂級公共類的名稱與源文件名稱必須一致。
121) OOP 中的 組合、聚合和關(guān)聯(lián)有什么區(qū)別?(答案)如果兩個對象彼此有關(guān)系,就說他們是彼此相關(guān)聯(lián)的。組合和聚合是面向?qū)ο笾械膬煞N形式的關(guān)聯(lián)。組合是一種比聚合更強力的關(guān)聯(lián)。組合中,一個對象是另一個的擁有者,而聚合則是指一個對象使用另一個對象。如果對象 A 是由對象 B 組合的,則 A 不存在的話,B一定不存在,但是如果 A 對象聚合了一個對象 B,則即使 A 不存在了,B 也可以單獨存在。
122)給我一個符合開閉原則的設(shè)計模式的例子?(答案)開閉原則要求你的代碼對擴展開放,對修改關(guān)閉。這個意思就是說,如果你想增加一個新的功能,你可以很容易的在不改變已測試過的代碼的前提下增加新的代碼。有好幾個設(shè)計模式是基于開閉原則的,如策略模式,如果你需要一個新的策略,只需要實現(xiàn)接口,增加配置,不需要改變核心邏輯。一個正在工作的例子是 Collections.sort() 方法,這就是基于策略模式,遵循開閉原則的,你不需為新的對象修改 sort() 方法,你需要做的僅僅是實現(xiàn)你自己的 Comparator 接口。
123)抽象工廠模式和原型模式之間的區(qū)別?(答案)
124)什么時候使用享元模式?(答案)享元模式通過共享對象來避免創(chuàng)建太多的對象。為了使用享元模式,你需要確保你的對象是不可變的,這樣你才能安全的共享。JDK 中 String 池、Integer 池以及 Long 池都是很好的使用了享元模式的例子。
Java 面試中其他各式各樣的問題
這部分包含 Java 中關(guān)于 XML 的面試題,JDBC 面試題,正則表達式面試題,Java 錯誤和異常及序列化面試題
125)嵌套靜態(tài)類與頂級類有什么區(qū)別?(答案)一個公共的頂級類的源文件名稱與類名相同,而嵌套靜態(tài)類沒有這個要求。一個嵌套類位于頂級類內(nèi)部,需要使用頂級類的名稱來引用嵌套靜態(tài)類,如 HashMap.Entry 是一個嵌套靜態(tài)類,HashMap 是一個頂級類,Entry是一個嵌套靜態(tài)類。
126)你能寫出一個正則表達式來判斷一個字符串是否是一個數(shù)字嗎?(解決方案)一個數(shù)字字符串,只能包含數(shù)字,如 0 到 9 以及 +、- 開頭,通過這個信息,你可以下一個如下的正則表達式來判斷給定的字符串是不是數(shù)字。
127)Java 中,受檢查異常 和 不受檢查異常的區(qū)別?(答案)受檢查異常編譯器在編譯期間檢查。對于這種異常,方法強制處理或者通過 throws 子句聲明。其中一種情況是 Exception 的子類但不是 RuntimeException 的子類。非受檢查是 RuntimeException 的子類,在編譯階段不受編譯器的檢查。
128)Java 中,throw 和 throws 有什么區(qū)別?(答案)
throw 用于拋出 java.lang.Throwable 類的一個實例化對象,意思是說你可以通過關(guān)鍵字 throw 拋出一個 Error 或者 一個Exception,如:throw new IllegalArgumentException(“size must be multiple of 2″)
而throws 的作用是作為方法聲明和簽名的一部分,方法被拋出相應(yīng)的異常以便調(diào)用者能處理。Java 中,任何未處理的受檢查異常強制在 throws 子句中聲明。
129)Java 中,Serializable 與 Externalizable 的區(qū)別?(答案)Serializable 接口是一個序列化 Java 類的接口,以便于它們可以在網(wǎng)絡(luò)上傳輸或者可以將它們的狀態(tài)保存在磁盤上,是 JVM 內(nèi)嵌的默認序列化方式,成本高、脆弱而且不安全。Externalizable 允許你控制整個序列化過程,指定特定的二進制格式,增加安全機制。
130)Java 中,DOM 和 SAX 解析器有什么不同?(答案)DOM 解析器將整個 XML 文檔加載到內(nèi)存來創(chuàng)建一棵 DOM 模型樹,這樣可以更快的查找節(jié)點和修改 XML 結(jié)構(gòu),而 SAX 解析器是一個基于事件的解析器,不會將整個 XML 文檔加載到內(nèi)存。由于這個原因,DOM 比 SAX 更快,也要求更多的內(nèi)存,不適合于解析大 XML 文件。
131)說出 JDK 1.7 中的三個新特性?(答案)雖然 JDK 1.7 不像 JDK 5 和 8 一樣的大版本,但是,還是有很多新的特性,如 try-with-resource 語句,這樣你在使用流或者資源的時候,就不需要手動關(guān)閉,Java 會自動關(guān)閉。Fork-Join 池某種程度上實現(xiàn) Java 版的 Map-reduce。允許 Switch 中有 String 變量和文本。菱形操作符(<>)用于類型推斷,不再需要在變量聲明的右邊申明泛型,因此可以寫出可讀寫更強、更簡潔的代碼。另一個值得一提的特性是改善異常處理,如允許在同一個 catch 塊中捕獲多個異常。
132)說出 5 個 JDK 1.8 引入的新特性?(答案)Java 8 在 Java 歷史上是一個開創(chuàng)新的版本,下面 JDK 8 中 5 個主要的特性:Lambda 表達式,允許像對象一樣傳遞匿名函數(shù)Stream API,充分利用現(xiàn)代多核 CPU,可以寫出很簡潔的代碼Date 與 Time API,最終,有一個穩(wěn)定、簡單的日期和時間庫可供你使用擴展方法,現(xiàn)在,接口中可以有靜態(tài)、默認方法。重復(fù)注解,現(xiàn)在你可以將相同的注解在同一類型上使用多次。
133)Java 中,Maven 和 ANT 有什么區(qū)別?(答案)雖然兩者都是構(gòu)建工具,都用于創(chuàng)建 Java 應(yīng)用,但是 Maven 做的事情更多,在基于“約定優(yōu)于配置”的概念下,提供標準的Java 項目結(jié)構(gòu),同時能為應(yīng)用自動管理依賴(應(yīng)用中所依賴的 JAR 文件),Maven 與 ANT 工具更多的不同之處請參見答案。
這就是所有的面試題,如此之多,是不是?我可以保證,如果你能回答列表中的所有問題,你就可以很輕松的應(yīng)付任何核心 Java 或者高級 Java 面試。雖然,這里沒有涵蓋 Servlet、jsp、JSF、JPA,JMS,EJB 及其它 Java EE 技術(shù),也沒有包含主流的框架如 Spring MVC,Struts 2.0,Hibernate,也沒有包含 SOAP 和 RESTful web service,但是這份列表對做 Java 開發(fā)的、準備應(yīng)聘 Java web 開發(fā)職位的人還是同樣有用的,因為所有的 Java 面試,開始的問題都是 Java 基礎(chǔ)和 JDK API 相關(guān)的。如果你認為我這里有任何應(yīng)該在這份列表中而被我遺漏了的 Java 流行的問題,你可以自由的給我建議。我的目的是從最近的面試中創(chuàng)建一份最新的、最優(yōu)的 Java 面試問題列表。
Java EE 相關(guān)的面試題
為了做 Java EE 的朋友,這里列出了一些 web 開發(fā)的特定問題,你們可以用來準備 JEE 部分的面試:
10 大 Spring 框架面試題及答案(參見)10 個非常好的 XML 面試問題(Java 程序員)(參見)20 個非常好的設(shè)計模式面試問題(參見)10個最流行的 Struts 面試題(Java 開發(fā)者)(參見)20 個 Tibco Rendezvous 及 EMS 的面試題(更多)10 個最頻繁被問到的 Servlet 面試問題及答案(參見)20 個 jQuery 面試問題(Java Web 開發(fā)者)(列表)10 個非常好的 Oracle 面試問題(Java 開發(fā)者)(參見)10 大 來自 J2EE 面試中的 JSP 問題(更多)12 個很好的 RESTful Web Services 面試問題(參見)10 大 EJB 面試問題及答案(參見)10 大 JMS 及 MQ 系列面試題及答案(列表)10 個非常好 Hibernate 面試問題(Java EE 開發(fā)者)(參見)10 個非常好的 JDBC 面試題(Java 開發(fā)者)(參見)15 個 Java NIO 和網(wǎng)絡(luò)面試題及答案(參見)10 大 XSLT 面試題及答案(更多)15 個來自 Java 面試的數(shù)據(jù)結(jié)構(gòu)和算法問題(參見)10 大 Java 面試難題及答案(參見)40 個核心 Java 移動開發(fā)面試題及答案(列表)
推薦給 Java 面試者的書籍如果你正為 Java 面試尋找好的準備,你可以看一下下面的書籍,這些書籍包含了理論及編碼的相關(guān)問題Markham 的 Java 編程面試揭秘(參見)破解編碼面試:150 個編程問題及解答(參見)程序面試揭秘:尋找下一份工作的秘密(參見)
如果覺得我的文章對你有幫助請在下面評論一下告訴我,謝謝!
學(xué)習(xí)Java的同學(xué)注意了!!!學(xué)習(xí)過程中遇到什么問題或者想獲取學(xué)習(xí)資源的話,歡迎加入Java學(xué)習(xí)交流群,群號碼:523047986 我們一起學(xué)Java!
Java? 著作權(quán)歸作者所有 舉報文章新聞熱點
疑難解答