Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
x Java 程式設計師面試寶典
簡介
從某些方面來說,面試特別重要,特別是在面對面接受技術測驗的時候。
本書的設計,是指導如何準備 Java 程式設計師的面試,幫助克服面試時的恐懼感與擔
憂。本書的方法是給予足夠的練習素材,如此便會有信心面對任何問題。
本書涉及的技術概觀 本書使用的 Java 版本是 Java SE 7,如果你是有經驗的 Java 程式設計師,但對 Java 7
並不了解,以下是一些新的語言特性與 API 介紹。
Diamond 運算子
在 可 能 情 況 下 , 編 譯 器 可 以 推 斷 出 一 般 實 體 的 型 別 。 這 代 表 你 可 以 撰 寫
List<Integer> numbers = new ArrayList<>(),而不需撰寫 List<Integer> numbers =
new ArrayList<Integer>()。這樣在操作集合時,特別是在集合中出現巢狀集合的狀
況下,可大量減少重複的程式碼。
在 switch 中使用字串
Java 的 switch 指令,最初只能處理數值型別。在 Java 5 介紹的列舉型別,就可以使
用在 switch中。從 Java 7 開始,String物件便可以在 switch中使用。
新的檔案 I/O 函式庫
Java 7 引入一個新的 I/O 函式庫,其重點是在平台獨立性,以及平行處理的 I/O
機制。
還有更多的功能已引入,其中包括自動資源管理,且開發人員可用二進位格式表達字
面資料。本書內容均以 Java 7 為準。讀者應預期面試人員都使用最新版本的 Java,所
以目標應該是讓自己的技術能跟上語言的最新版本。
有些 Java 的框架與函式庫仍未與 Java 7 完全相容,所以在使用特定元件時,要確認
所讀文件的版本是否為最新。
本書的組織安排 這本書分成三個獨立的大方向。
簡介 xi
第一部分:面試流程領航
第一部分中的各章,主要涵蓋兩大主題,分別談到在面試中展現自己的方法,並了解
某些並非 Java 獨有的一般主題,後者很可能會在技術測驗時出現。
第 1 章:剖析面試類型
本章介紹大部分招聘過程,從電話篩選面試,到面對面的技術測試,到與用人單位的
主管交談。
第 2 章:寫出引人注目的簡歷
簡歷和求職信,對潛在的雇主來說,便是求職人員給他們的第一印象。本章介紹如何
讓簡歷脫穎而出,使用適合的表達方式,以及提示招聘人員所看的重點為何。
第 3 章:技術測試和面試的基礎
雇主會希望能儘快測試你的技術程度。本章討論了不同的程式設計方法和可應用的技
術測試,以及如何最好地為每個情境準備。
第 4 章:撰寫核心演算法
技術測試的熱門主題,是一些核心的電腦科學概念,包括排序和搜尋。本章將指導排
序和搜尋的一些不同的演算法,並討論每種方法的優劣。
第 5 章:資料結構
常常會搭配排序和搜尋等電腦科學問題。有效率的資料儲存和表示,是面試的另一個
常見主題。第 5 章會討論串列、樹、圖,以及集合,另外還有它們的表達和使用。
第 6 章:設計模式
本章涵蓋了幾種物件導向設計模式,並且還顯示一些 Java 函式庫類別的案例用法。
第 7 章:實作面試時常考的演算法
本章主要介紹一些常見的面試問題和步驟,並使用 Java 去實作。許多問題都是從技術
面試網站 interviewzen.com來的。
第二部分:Java 核心
這個部分的章節,涵蓋面試人員在應徵者身上,預期想看到的大部分東西。
xii Java 程式設計師面試寶典
第 8 章:Java 基礎
本章涵蓋了許多 Java 的語言特性,對有經驗的 Java 開發人員來說,算是要點
重述。
第 9 章:使用 JUnit 測試
貫穿全書的一個核心主題,是關於單元測試的使用和關注。本章介紹 JUnit,並敘述
如何使用它來檢查所有假設和斷言。
第 10 章:了解 Java 虛擬機
所有合格的開發人員,都對於使用的平台有所了解,在 Java 也不例外。本章涵蓋了
JVM 的一些特色,以及 JVM 和 Java 語言之間的互動。
第 11 章:平行處理
本章探討 Java 的執行緒模型及其用法。另外,本章還介紹了 actor,這是近期最新的
平行處理方法。
第三部分:元件和框架
這部分會研討在不同的領域中使用 Java,從資料庫到網頁伺服器,或從某些主流的框
架(比如 Hibernate 和 Spring)到構建和分佈企業層級應用程式的工具。本章很可能
在面試中擔任某個特殊角色,面試人員會預期求職者具備其中一些章節的知識,並且
常將其列於工作要求之中,便能吸引你對該職缺投遞履歷。
第 12 章:整合 Java 應用程式與資料庫
許多夠大的 Java 應用程式,都會有一個資料庫元件。本章會介紹 SQL、操作資料庫
的語言標準,以及 Java 和 SQL 如何配合工作。
第 13 章:建立網路應用程式
Java 為市場主流語言之一,可用於建立應用程式,並透過 HTTP 協定傳輸資料。本章
會介紹三個主流框架:Tomcat、Jetty,以及 Play。
第 14 章:使用 HTTP 和 REST
本章會看另一個在 HTTP 上的用途:建立和使用網路服務,使用如含狀態傳輸
(Representational State Transfer, REST)的風格。
簡介 xiii
第 15 章:序列化
序列化是傳輸結構化資料的方法。本章介紹了三種方法:Java 自己的序列化機制,以
及用 XML 或 JSON 執行平台獨立的方法。
第 16 章:Spring Framework
一個比較主流的應用程式框架,Spring 被許多雇主使用在應用程式安裝上,就算沒用
在全部的應用程式,至少也是部分的應用程式。本章會看幾個 Spring 框架的元件,包
含核心應用程式上下文、資料庫整合,以及整合測試。
第 17 章:使用 Hibernate
Hibernate 是把關聯資料庫的資料映射到 Java 物件的框架。本章介紹 Hibernate,以及
如何用它來建立和操作物件。
第 18 章:有用的函式庫
Java 有很多有用的、可重複使用的函式庫。第 18 章分析三種比較普遍的函式庫:
Apache Commons、Guava,以及 Joda Time。
第 19 章:用 Build Tool 開發
任何大型的 Java 應用程式,尤其是有多個開發人員,都需要一個管理良好的程序,來
建立應用程式並打包。本章介紹的是 Maven 和 Ant,這是建立 Java 應用程式的兩個
最主流工具。
第 20 章:Android
最後一章介紹了 Java 語言更現代的用法:開發 Android 行動應用程式。本章會關注
Android SDK 的關鍵元件,以及它們之間如何整合。
附錄 A:Scala 簡介
簡單介紹 Scala,這是一個新的語言,獲得許多 Java 開發團隊廣泛採用,因為它採用
了 JVM 作為其平台。本章會介紹其基礎概念、函數式程式設計的概念,以及一些跟
不變性有關的慣例。
本書的目標讀者群 本書是給具備一定經驗的 Java 開發人員看的:對 Java 有一定的了解,且也使用了一
段時間,但不見得熟悉,甚至是對某些章節的主題完全陌生。如果從未使用過 Java,
xiv Java 程式設計師面試寶典
本書也可能會有所幫助,特別是在第二部分的章節,但你可能還是得先花時間學習
Java 的基礎。
假設你正進行面試,甚至可能發現本書的一些用途:請從中取得靈感,便可在面試途
中發問。
你需要的工具 可以從 http://www.oracle.com/technetwork/java/javase/downloads/index.html 下載
最 新 的 Java JDK 。 最 專 業 的 開 發 人 員 會 使 用 整 合 開 發 環 境 ( Integrated
Development Environment, IDE)編寫 Java 原始碼。兩個比較普遍的 IDE,分別是
IntelliJ(可在 http://www.jetbrains.com/idea/download/index.html 下載免費的社群
版),以及 Eclipse(可在 http://www.eclipse.org/downloads/下載)。一些比較有
經驗的面試官會提供一台電腦和 IDE,用於測試你的技術,所以應該要熟悉這兩個
IDE 的相關基礎常識。
下載範例原始碼 所 有 本 書 的 範 例 原 始 碼 可 從 www.wiley.com/go/javaprogramminginterviews 或
http:/books.gotop.com.tw/download/ACL041600 下載。你可能會發現下載、編輯,以
及編譯該原始碼,是有幫助的,尤其是對於一些不太熟悉的主題有幫助。
總結 本書對於想擔任 Java 開發人員的人,並不是捷徑,而是輔助你尋找下一份工作。它應
該有助於學習面試人員在招聘過程中經常發問的主題。
不管是面對任何詢問,或是碰到性質不合、令人氣餒的面試,經驗都是非常有用的。
你必須練習和實踐技能和技術,技術會因為花費更多的時間磨練而提高。培養面試的
經驗是很困難的,因為每個雇主進行面試的過程不同,且整個過程也不完美。潛在的
雇主必須考慮許多變化因素,而非只在確定聘用前,思考「這個人選夠好嗎?」,另
外還會有預算考量、團隊契合度,甚至連面試官的心情都有影響力。
如果你被某家公司拒絕,盡量不要太介意,而要試圖利用這次經驗,去思考下次面試
會碰到什麼問題。
也請記住,面試是一個雙向的過程:可以詢問工作內容、同事,以及辦公室的生活型
態。在該職務不適合你時,不要害怕主動拒絕。
祝你在面試過程順利,盡量享受這趟旅程!希望本書能幫助你得到夢想中的工作。
設計模式
軟體設計模式使用一個以上的物件共同解決一個常見的使用案例。這些案例往往注重
程式碼的重用、延伸,或為未來的開發提供堅實的基礎。
作為物件導向的語言,Java 使用的許多設計模式遍及整個標準函式庫 API,且要自行
建立一些常見設計模式的實作相當簡單。
本章將介紹幾種常見的設計模式,檢視標準 Java API 中看到的幾種,也實作一些模式。
軟體設計模式即便沒有數千,也有數百種存在。日常工作上可能會建立一些新模式。
這裡所談論的模式,是一些更常見且大多數人熟知的模式。面試人員常喜歡問關於設
計模式的問題,因為這有大量的討論空間,且它們的定義很明確。
嘗試本章範例,思考自己的情況,看是否能把模式用在那些地方。試圖證明給定的模
式是否適合某個特定情況,再看看是否能作出其他的模式也適合同樣的情況。它並非
總是可行的,但有時在某些情況下,模式可以互換。
研究範例模式
建構者模式(Builder Pattern)的用處多大?
若想建立一個有許多欄位的物件,使用建構子可能有所不便且令人困惑。想像下面的
類別定義,它也可能用於獸醫的資料庫:
Java 程式設計師面試寶典 52
private final Date dateOfBirth; // 非必要欄位 private final String emailAddress; // 非必要欄位 ...
為了讓這些欄位的任意組合建立一個有效的 Pet 物件,至少需要四個建構子以及許多
參數,包含所有需要的欄位,還有選用欄位的所有組合。如果打算添加更多的選用欄
位,很快會變得難以管理,甚至難以理解。
一種方法是完全不使用建構子,刪除欄位中的 final 修飾字,而僅使用 setter 方法設
定 Pet物件。這樣做的主要缺點是,會建立無效的 Pet物件:
一個 Pet 物件的定義是把 animal、petName、ownerName、address,以及 telephone 等
欄位都設定。
使用建構者模式(Builder Pattern)可以減輕這種狀況的影響。使用建構者模式建立
一個同伴物件( companion object),稱為建構者( builder),會建設領域合法
(domain-legal)的物件。這種作法也比單純使用建構子更清楚。範例 6-1 的內容,是
用建構者建立 Pet物件。
範例 6-1:用建構者模式建構物件
// 通過測試,未拋出例外
Chapter 6 設計模式 53
Builder 類別是 Pet 類別的一部分,全權負責建立 Pet 物件。使用建構子,參數順序
會決定每個參數如何使用。若每個參數都有明確的函式方法能準確了解每個值的用
途,便可以用隨意的順序呼叫它們。build 方法呼叫 Pet 物件的實際建構子,且確實
回傳 Pet物件。建構子目前的權限為 private。
還要注意,呼叫建構者方法的慣例是將其串聯( chain ) (builder.withXXX().
withYYY()...),這允許更簡潔的定義。範例 6-2 會示範代表 Pet 類別的 Builder 類別
如何實作。
範例 6-2:實作建構者模式
(接下頁)
Java 程式設計師面試寶典 54
範例 6-2:(續)
private final Date dateOfBirth; // 非必要欄位 private final String emailAddress; // 非必要欄位
如果領域物件(domain object)有預設值,便可以將其設於建構者欄位,然後在必要
時覆蓋它們。這考慮到更簡潔的物件架構。範例 6-3 所示為另一種建構者,但使用預
設值。
Chapter 6 設計模式 55
範例 6-3:在建構者中使用預設值
之後就可以輕鬆地建立小說類書籍,而無需指定型別:
可以給個策略模式(Strategy Pattern)的例子嗎?
策略模式能夠輕鬆地切換演算法的具體實作細節,而不需要完全重寫。甚至可以在執
行時期切換實作。策略模式通常用於結合相依性注入(dependency injection),以允
許實作部分與專門用於測試的程式碼交換,或是允許模仿的實作( mocked
implementation)用來代替。
範例 6-4 示範如何使用策略模式撰寫簡單的記錄器。
Java 程式設計師面試寶典 56
範例 6-4:用策略模式實作記錄器
// 處理 IOException
這使你可以使用 Logging 介面編寫程式碼,且若日誌記錄寫入至控制台輸出或一個檔
案中,則不需在意要記錄的程式碼。透過編寫介面的程式碼,而不是一個具體的實
作,便可以使用 ConsoleLogging 策略測試程式碼,並把 FileLogging 用於生產。日
後,也可以添加多個 Logging 的實作,且以介面為背景撰寫的任何程式碼都不會改
變,但能夠使用新的實作。
範例 6-5 示範如何使用客戶端程式碼中的 Logging 介面,另外有三個測試範例:其中
兩個使用 ConsoleLogging 和 FileLogging 策略,以及一個使用的 Mockito 模仿。如果
不熟悉模仿(mocking),第 9 章會說明其運作方式。
範例 6-5:使用日誌記錄策略
Chapter 6 設計模式 57
在 Java 應用程式的記錄器
在範例 6-3 與 6-4 使用的程式碼,純粹是如何使用策略模式的例子。永遠不要
用這種記錄方式實作或撰寫記錄器。Java 有許多函式庫專用於日誌輸出,比如
Log4J 和 SLF4J。看看這些函式庫,再看看你是否能理解策略模式如何實作完
成,以及理解該如何解釋不同行為。
Java 程式設計師面試寶典 58
使用策略模式便能延後決定使用哪種實作,直到執行時期為止。Spring 框架使用
XML 檔案來建構物件及其相依關係,它是在執行時期讀取,並允許實作之間的快速
變化而無需重新編譯。第 16 章有更多資訊。
如何使用樣版模式(Template Pattern)?
樣版模式是用來延遲或把演算法的部分或全部步驟委託給子類別。共同的行為可以在
父類別定義,然後特定的變化都寫在子類別。範例 6-6 所示為堆疊的定義,背後其實
是 LinkedList和一個用來過濾 Stack實體的介面(稱為 StackPredicate)。
範例 6-6:堆疊
Chapter 6 設計模式 59
StackPredicate 是樣版模式的實作,該模式允許客戶端程式碼確實定義過濾的運作
方式。
filter 方法有其邏輯:它會走訪堆疊的每個值,並詢問 predicate,是否該值要包含在
過濾堆疊以回傳。filter方法的邏輯完全從 StackPredicate的特定邏輯分離,才能決
定是否要過濾給定的有效值。
範例 6-7 示範了 StackPredicate 兩種可能的實作:一種是只允許偶數,而另一個沒有
影響:
範例 6-7:實作 StackPredicate 樣版
Java 程式設計師面試寶典 60
分離 StackPredicate 具有許多優點。它允許 Stack 類別的客戶端以自己的需求過濾,
完全無需修改 Stack 類別。此外,StackPredicate 實作屬於程式碼的一個單元,因
此,可以完全隔離測試,而不需要一個堆疊實體。
常用的模式
試述裝飾者模式(Decorator Pattern)的實作?
裝飾者模式,可以更改或設定特定物件的功能組態,如添加按鈕或滾動捲軸,也可確
實定義如何從相同要素中對兩個不同的客戶模擬三明治順序。
Java 原本的 IO 類別,在讀取和寫入 JVM 之外的來源方面,廣泛使用裝飾者模式。
InputStream 和 OutputStream 類別及其子類別使用裝飾者模式讀取和寫入資料的方
法,是由實作類別來定義,而這些實作往往可以串聯一起,以提供能有效率讀取或寫
入來源的方式。
檢視 OutputStream 抽象類別,它有一個方法必須在實作中定義,該方法僅是寫入一個
位元組:
可以使用其他方法來大量寫入位元組,預設情況下每個位元組都會呼叫前述的方法。
依實作方式而定,覆蓋這些方法可能更有效率。
許多 OutputStream 的實作會執行必要的行動,然後委托給其他的 OutputStream。這些
實作會以另一個 OutputStream作為建構子的參數。
OutputStream 會實際執行資料寫入(如 FileOutputStream 或 SocketOutputStream),
而不委託其 write 方法到另一個串流,所以不需要另一個 OutputStream 物件用在其建
構子的參數。
範例 6-8 示範使用裝飾者模式,在位元組陣列寫入硬碟前,把幾個操作串聯。
範例 6-8:使用裝飾者模式寫入硬碟
Chapter 6 設計模式 61
該測試的前五行,是定義要寫入的檔案,以及把資料寫入檔案的方式。FileOutputStream
將檔案寫入硬碟。BufferedOutputStream 會快取所有呼叫,且一次寫入數個位元組。
在寫入硬碟時,這可能有龐大的效率增益。ObjectOutputStream 是 Java 內建的序列化
機制,用來把物件與基本型別寫入串流。序列化會在第 15 章討論更為詳細。
請注意,這裡說的 ObjectOutputStream 不知道檔案在哪裡被寫入,它僅是委託給另一
個 OutputStream。這種模式的強大之處在於可以提供新的 OutputStream 實作,且能與
之前存在的部分合作。
比如說,如果想記錄每次呼叫 BufferedOutputStream 的事件,就可以輕鬆地撰寫某個
實作,且它會與前面定義的部分搭配運作。或如果想在寫入資料之前將其加密,這也
能做到。
如果想在寫入硬碟之前對資料進行壓縮,可以使用由 Java 標準函式庫提供的
GZIPOutputStream類別。
記住,在 OutputStream 串聯當中定義的順序可能是重要的。當讀回的資料在儲存前被壓
縮,你肯定會想用 GZIPInputStream去了解資料,再使用其他裝飾的 InputStream物件。
試敘述享元模式(Flyweight Pattern)的實作?
享元模式的用處,是在幾個物件的情況,且許多物件可能代表相同的值,才能發揮。
在這些情況下,只要該物件是不可改變的,就可能會共享值。範例 6-9 示範來自 Java
標準函式庫的例子,是從 Sun 的 Integer類別實作而來。
範例 6-9:運作中的享元模式
Java 程式設計師面試寶典 62
valueOf 方法會檢查給定的參數值,且如果它是預先快取值,則該方法會回傳建構的
實體,而不是建立新副本。快取的預設範圍是-128 到 127。快取會在 static 區塊中設
定初始值,所以在初次建立時,在運作時的 JVM 裡,會有參考指向的 Integer:
// 省略建立快取大小
範例 6-10 證明快取使用了享元模式,因為該測試會檢查兩個實體,但實際上它們是
同一個實體,而不僅僅是相等的物件。
範例 6-10:證明 Integer.valueOf 使用享元模式
這個屬性只會在 Integer 物件是不可變的狀況下存在。若建構 Integer 物件後,才修
改其值,之後當它搭配享元模式使用時,修改值會出現連鎖效應,影響每個指向該物
件的參考。
若曾經建立 Integer 物件,便一定要用 valueOf 方法才會有享元模式的優點。如果呼
叫 new,即使新實體處於快取值的門檻內,也必定會建立。
享元模式適用於很多情況,該模式的另一種實作稱為空物件模
式(Null Object Pattern)。這種模式採用了輕量級的物件來
代表空值。
當建立如二元樹的資料結構,其葉子沒有子節點。依實作而
定,可能使用 null 參考就夠了,或者是使用一個空物件。可
以想像成每片葉子都有自己的空物件,但在實踐上,可以使用
單一個輕量級物件。範例 6-1 示範使用空物件模式的二元樹物
件參考。 Null
圖 6-1
Chapter 6 設計模式 63
如何使用單體模式(Singleton Pattern)?
單體其實就是一個類別,而該類別只允許建立一個實體。它經常用於建立給第三方使
用的單一入口,例如資料庫或網站服務,連線數便可以很容易地在一個地方管理和
配置。
限制單體類別的客戶端只能有一個實體,可以證明具有挑戰性。範例 6-11 為單純的
初次嘗試。
範例 6-11:有問題的單體
// 在此操作
這裡的方法被稱為延遲初始化(lazy initialization):Singleton 實體只能在首次需要
時建立。乍看之下,它看起來與其他對 getInstance()的呼叫很像,都是回傳相同的
實體。然而,如果 INSTANCE為 null,且一個執行緒會在 if指令後,卻在 INSTANCE初
始化之前切換,則第二個以上的執行緒呼叫的 getInstance()也會有 if 指令回傳
true,並建立一個新物件。這可能會導致發生怪異的行為,更糟的是,記憶體洩漏
(memory leak)導致 JVM 當機。
Java 5 引入 Enum 型別。如果建立的 Singleton 作為一個單元素的 Enum,JVM 保證
(guarantees)只會建立一個實體,如範例 6-12 所示。
範例 6-12:使用 Enum 代表 Singleton
// 在此操作
Java 程式設計師面試寶典 64
請注意,使用單體模式可能導致其他問題:要單獨測試可能非常困難,尤其是如果
Singleton 進行重量級的操作,如寫入資料庫。只管理任何「類似單體」的物件作為
類別相依往往更好,且使用相依性注入框架以建構一個物件。
單體在特定的應用程式運作得很好,比如桌面或行動應用程式上的 GUI,或者當知道
不會同時有很多用戶的狀況。如果正在建構大型、可擴展的伺服器應用程式,之後單
體物件往往是大多數效能瓶頸的根源。
總結 本章算輕鬆地看看常見的物件導向軟體設計模式。確保了解其如何運作,以及為什麼
使用它們。 Java 語言和函式庫中的其他模式都沒有在這裡討論,比如迭代器模式
(Iterator Pattern)、工廠模式(Factory Pattern)等等。一旦熟悉了模式,便應該能
夠很容易地在整個語言和函式庫看到它們的蹤跡。
花時間來閱讀和研究更多的設計模式。許多免費的網路資源談到更多的設計模式與範
例實作。最早的設計模式書籍,《物件導向設計模式》(Design Patterns: Elements of
Reusable Object-Oriented Software , Ralph Johnson 、 John Vlissides 、 Richard
Helm,以及 Erich Gamma 合著,Addison-Wesley,1994 年 10 月)是這個主題非常
棒的資源,雖然裡面的範例並非用 Java 撰寫。
一旦習慣使用物件導向的模式,應該檢查在軟體中還有什麼地方可以看到模式。另
外,更現代的軟體模式論述,涵蓋整個系統會發現的模式書籍,是《Enterprise Integration Patterns 》( Gregor Hohpe 與 Bobby Woolf 合著, Addison-Wesley
Signature 系列,2003 年 10 月)。
有更多使用設計模式的經驗,在審查程式碼,甚至 API 文件時,就越會發現它們的存
在。這可以讓你更快了解和學習新的 API 和功能。
下一章將著眼不同種類的模式:是一些常出現,也是面試人員最愛問的問題。