一刷 2000 冊 (2003/08)  

《Practical Java》
中文版 (繁體)

侯捷 / 劉永丹 譯

practical-java-b5.jpg (69294 bytes)

封面封底全圖

本書範例  PraticalJavaCode.zip

繁體中文版勘誤


□中譯書名(暫名):Practical Java 中文版
□適合對象:中高階 Java 程式員。
□製作特色:與原文本頁頁對譯,含 index,網片輸出,平裝
□內容特色:68 條 Java編程準則與注意事項

開放檔案如下:

檔名 內容 大小 bytes
practical-java-chap1-3.pdf

不需密碼即可開啟。
檔案含簡略書籤(目錄連結)

扉頁、譯序、目錄、細目、前言、致謝、1-3章  
PraticalJavaCode.zip 本書範例源碼
(原作者提供)
139,288

不需密碼即可開啟。檔案不含書籤(目錄連結)

如欲下載,請將滑鼠移至上述 hyperlink,按右鍵,再選【另存目標...】即可。

 

譯序
by 侯捷

面對Java,可從兩方面看待,一是語言,一是平台。本書談的是Java語言,以下我所言種種,也是指Java語言。

Java是一門優秀的物件導向編程語言(Object Oriented Programming Language, OOPL)。什麼是「物件導向」?如何才稱得上「優秀」?前者可定量定性,客觀;後者往往流於個人感受,主觀!所以雖然物件導向語言有著幾近一致的條件和門檻註1)(封裝、繼承、多型),孰優孰劣卻是各人心中一把尺。儘管如此,無人可以否認Java語言在OOP(物件導向編程)上擁有良好的特性和優越的表現。

註1:我常憶起網絡論壇上時可與聞的一種怪誕態度。有一派人士主張,OO是一種思想,一種思考模式,任何語言都能夠實現它,因而侈言「C或assembly語言也能OO」。任何語言各有用途,這是完全正確的;OO是一種思維,這話也是對的。任何語言都能夠實現OO,這話對某些人也許是對的,對99.9999%的人是錯的。以non-OO語言實現OO思維,非但達成度極低,也非人人能為。Edmund Hillary(艾德蒙 希拉瑞)能達到的高度,你未必達得到 — 事實上你通常達不到。(註:Edmund Hillary是第一位登上聖母鋒的地球人,1953年英格蘭遠征隊員。)

我所謂良好的OOP特性,指的是Java提供了許多讓程式員得以輕鬆表達物件導向技術與思維的語言關鍵字(keywords)如class, abstract, interface, extends, implements, public, protected, private, final, static, finalize…,又提供條理清晰結構分明的檔案組織方式如package, import,又擁有嚴謹而靈活的動態型別系統(dynamic type system)使得以提供RTTIReflection機制,並擁有一個優秀、涵蓋面廣、擴充性強的標準程式庫(Java Libraries)。

這些優秀的語言構件(constructs)雖然好用易用,但不論就技術面或應用面或效率考量,還是有許多隱微細節散佈其中,例如object creation, object initialization, Cloneable, Serializable, Equality, Immutability, Multithreading (Synchronization), Exception Handling…,在在需要Java程式員深入認識與理解。

市面上Java書籍極多,專注於「編程主題式探討」並「以獨立條款呈現」的書籍比較少。這類書籍面向中高階讀者,不僅選題必須饒富價值、探討必須極為深刻,各主題最好還獨立以利選擇閱讀,卻又最好彼此前後呼應環環相扣,並附良好交叉索引,予讀者柳暗花明的強烈衝擊。此種「專題條款」式的表現風格,在Scott Meyers的《Effective C++》和《More Effective C++》二書面世之後獲得許多讚揚,也引來許多追隨。

Practical Java》和《Effective Java》二書,對前述重要而基礎的技術細微處有著詳盡、深刻、實用的介紹和剖析和範例,又以獨立條款之姿展現,在內容的紮實度、可讀性、易讀性上表現均十分良好。為此,秉持並承繼我為C++ 社群翻譯《Effective C++》、《More Effective C++》的態度和機緣,我很開心再次由我負責,將《Practical Java》和《Effective Java》二書中譯本呈獻給Java 社群。

考慮本書讀者應已具備Java編程基礎,對於各種英文術語已有良好的接受度,我在書中保留了許多英文術語,時而中英並陳,包括class, object, interface, reference, instance, array, vector, stack, heap…,也包括涉及Java關鍵字的一些用語如private, public, protected, static, abstract…,不勝枚舉(下頁另有一個扼要說明)。本書努力在字型變化上突顯不同類形的術語,以利讀者閱讀。本書支援網站有一個「術語  英中繁簡」對照表,歡迎訪問,網址如下。

Practical Java》由劉永丹先生和我合力完成。永丹做前期初譯工作,我負責後繼的文字修潤、技術檢閱、大局風貌。永丹技術紮實,文字用心。沒有他的協助,本書不可能在這個時間以這樣的品質面世。謝謝永丹。

本書每一章起始處都有作者匠心獨具收集的一些文摘語錄。我們雖勉力譯出,恐見識不足,貽笑大方,故均留下原文和出處,庶幾不誤讀者。

侯捷 2003/07/08 于臺灣.新竹

jjhou@jjhou.com(電子郵箱)
http://www.jjhou.com(繁體)(術語對照表http://www.jjhou.com/terms.htm
http://jjhou.csdn.net(簡體) (術語對照表http:// jjhou.csdn.net/terms.htm

p.s. 本書已就英文版截至2003/07/08之勘誤表修正於紙本。

■本書術語翻譯與保留之大致原則:

廣被大眾接受之術語,無需額外說明,不在此列。例如繼承(inheritance)、封裝(encapsulation)、多型(polymorphism)。

本書保留與Java關鍵字相關之術語不譯,例如class, interface, private, public, protected, static, final, abstract, synchronized, serializable…

本書保留資料結構名稱不譯,例如array, vector, list, map, set, stack, heap…"collection" 譯為「群集」。

"class" 及其所衍生之各種名詞如subclass, superclass, immutable class, mutable class, base class, derived class等皆保留不譯(時而英中並陳)。"object" 大多數時候譯為「物件」,時而保留。"object reference" 保留不譯,"reference" 亦不譯。

"type" 譯為「型別」。"parameter" 譯為「參數」,"argument" 譯為「引數」。"delegate", "delegation" 譯為「委託」,"aggregate", "aggregation" 譯為「聚合」。"composition" 譯為「複合」。

動詞 "create" 譯為「創建」或「建立」,描述物件之初次誕生。動詞 "refer" 譯為「指涉」或「指向」或「引用」。動詞 "dereference" 譯為「提領」。動詞 "override" 譯為「覆寫」。動詞 "overload" 譯為「重載」。

本書將Java class "methods" 譯為函式,因為它等價於其他編程語言之 "function"。若直譯為「方法」,行文缺乏術語突出感,恐影響閱讀流暢;若不譯,過於頻繁出現又恐影響版面觀感。

本書將Java class "fields" 譯為欄位,等價於C++ 語言之 "data member"

本書將 "clone" 譯為「克隆」(這一用詞在中國大陸極為普遍),映照 "copy" 之於「拷貝」。非單純保留 "clone" 是因為它時常做為動詞並頻繁出現,而我對術語的保留態度是儘量只考慮名詞(偶有形容詞)。

※「static欄位與instance欄位」、「reference物件與value物件」、「reference型別與primitive型別」等等術語保留部分英文,並使用特殊字型。

本書支援網站有一個「術語英中繁簡」對照表,歡迎訪問,網址見上頁。

術語翻譯有許多兩難之處,祈願讀者體諒;譯者勉力求取各方平衡,並儘可能於突兀處中英並陳。

-- 侯捷

 

 

細目
理論上,理論和實際並沒有區別;實際上,它們是有區別的。
In theory, there is no difference between theory and practice. But, in practice, there is.
Jan L.A. van de Snepscheut

一般技術(General Techniques

實踐1:引數是以傳值(by value)而非傳址(by reference)方式傳遞

所有Java objects都透過object reference而被取用。常見的一個誤解是Javaby reference方式傳遞引數。事實上所有引數都以by value方式傳遞。

實踐2:對不變的dataobject reference使用final

為了讓dataobject reference成為不變量,請使用final。注意,final僅僅令object reference自身成為不變量,並不限制它所指向之物件的改變。

實踐3:預設情況下所有non-static函式都可被覆寫(overridden

預設情況下,所有non-static函式都可以被subclass覆寫。但如果加上關鍵字final,便可防止被subclass覆寫。

實踐4:慎重選擇arraysVectors

arraysvectors是常見的容器類別(storage classes)。選用它們之前應該先瞭解它們的功用和特性。

實踐5:多型(polymorphism)優於instanceof

instanceof的許多用途可以因為改用多型而消除之。使用多型,程式碼將更清晰、更易於擴展和維護。

實踐6:必要時才使用instanceof

有時我們無法迴避使用instanceof。我們應該瞭解什麼情況下必須使用它。

實踐7:一旦不再需要object references,就將它設為null

不要忽視記憶體可能帶來的問題。儘管有了垃圾回收機制(garbage collection),你仍然需要關注你的程式碼如何運用記憶體。如果能夠領悟垃圾回收機制和記憶體運用細節,你就能夠更好地知道何時應該將object references設為null,那將導致高效的程式碼。

物件與相等性(Objects and Equality

實踐8:區分reference typeprimitive type

Java是物件導向的,但其操控的東西並非都是物件(objects)。理解reference typeprimitive types之間的差異,及它們在JVM中的表述(representation),會使你在運用它們時得以做出明智的選擇。

實踐9:區分 == equals()

== 用來測試基本型別的相等性,亦可判定兩個object references是否指向同一個object。若要測試values(值)或semantic(語意)相等,應使用equals()

實踐10:不要依賴equals()的預設實作(default implementation

不要不假思索地認定一個class總是會正確實作出equals()。此外,java.lang.Object提供的equals()大多數時候並非進行你想要的比較。

實踐11:實作equals()時必須深思熟慮

如果某個class的兩個objects「即使不佔用相同的記憶體空間,也被視為邏輯上相等」,那麼就該為這個class提供一個equals()

實踐12:實作equals()時優先考慮使用getClass()

實作equals()時請優先考慮採用getClass()。畢竟,「相同class下的objects才得被視為相等」是正確實作equals()的一個清晰簡明的解決方案。

實踐13:呼叫base class(基礎類別)的super.equals()

任何base class(除了java.lang.Object)如果實作equals(),其derived class都應該呼叫super.equals()

實踐14:在equals()函式中謹慎使用instanceof

唯有當你考慮允許「一個derived class object可以相等於其base class object」時,才在equals()中使用instanceof。使用這項技術前請先弄清楚其影響。

實踐15:實作equals()時需遵循某些規則

撰寫equals()並非那麼直觀淺白。如果想要恰當地實作出equals(),請遵循某些規則。

異常處理(Exception Handling

實踐16:認識「異常控制流」(exception control flow)機制

讓自己諳曉異常控制流程細節。瞭解這些細微之處有助於你迴避問題。

實踐17:絕對不可輕忽異常(Never ignore an Exceptions

一旦異常出現卻沒有被捕獲,拋出異常的那個執行緒(thread)就會中止運行。是的,異常意味錯誤,永遠不要忽略它。

實踐18:千萬不要掩蓋異常(Never hide an Exceptions

如果處理異常期間又從catchfinally區段拋出異常,原先的異常會因而被隱蔽起來。一旦發生這樣的事情,就會丟失錯誤資訊。你應當撰寫專門負責處理這種情形的程式碼,將所有異常回傳給呼叫者。

實踐19:明察throws子句的缺點

將一個異常加入某函式的throws子句,會影響該函式的所有呼叫者。

實踐20:細緻而全面地理解throws子句

任何函式的throws子句應當列出它所傳播的所有異常,包括衍生異常型別(derived exception types)。

實踐21:使用finally避免資源洩漏(resource leaks

不要忽視記憶體以外的資源。垃圾回收機制不會替你釋放它們。請使用finally確保記憶體以外的資源被釋放。

實踐22:不要從try區塊中回返

不要從try區塊中發出return指令,因為這個函式未必會立即從那兒回返。如果存在finally區段,它就會被執行起來並可能改變回傳值。

實踐23:將try/catch區塊置於迴圈(loop)之外

撰寫含有異常處理的迴圈時,請將trycatch區塊置於迴圈外部。在某些實作版本上,這會產生更快的執行碼。

實踐24:不要將異常(exceptions)用於流程控制

請將異常用於預期行為之外的情況。不要以異常來控制流程,請採用標準的語言流程構件(flow constructs),這樣的流程表達會更清晰更高效。

實踐25:不要每逢出錯就使用異常(exceptions

只有面對程式行為可能出乎預料的情境下才使用異常。「預期中的行為」應使用回傳碼(return codes)來處理。

實踐26:在建構式(constructors)中拋出異常

儘管建構式並非函式(method),因而不能回傳一個值,但建構式有可能失敗。如果它們失敗了,請拋出一個異常。

實踐27:拋出異常(exceptions)之前先將object恢復為有效狀態

拋出異常很容易,困難的是「將異常所引發的傷害減到最小」。拋出異常之前,應確保「如果異常被處理好,流程再次進入拋出異常的那個函式中,該函式可以成功完成」。

效能/效率(Performance

實踐28:先把焦點放在設計、資料結構和演算法身上

Java帶來最大效能提升的辦法就是:在設計和演算法中使用與語言無關的技術。因此,首先請將你的精力集中於這些上面。

實踐29:不要倚賴編譯期程式碼優化技術

Java編譯器生成的碼,通常不會比你自己撰寫的更好。別指望編譯器能夠多麼優化你的原始碼。

實踐30:理解運行期(runtime)程式碼優化技術

Java效能的大部分努力都圍繞著運行期優化展開。這種作法有利有弊。

實踐31:如欲進行字串接合,StringBuffer優於String

對於字串接合,StringBuffer class要比String class快許多倍。

實踐32:將object的創建成本(creation cost)降至最小

在許多物件導向系統中,「產生物件」意味著高昂的成本。瞭解成本所在,以及瞭解「加速物件產生速度」的技術,都可以導致更快的程式碼。

實踐33:慎防未用上的物件(unused objects

非必要別產生物件。非必要地產生物件,會減慢你的程式速度。

實踐34:將同步(synchronization)減至最低

宣告synchronized函式或synchronized區塊,會顯著降低效能。只在物件需要時才使用同步機制(synchronization)。

實踐35:儘可能使用stack變數

stack變數為JVM提供了更高效的byte code指令序列。所以在迴圈內重複取用static變數或instance變數時,應當將它們臨時儲存於stack變數中,以便獲得更快的執行速度。

實踐36:使用staticfinalprivate函式以允許實施inlining

以函式本體替換函式呼叫,會導致更快的程式碼。如果要令函式為inline,必須先宣告它們為staticfinalprivate

實踐37instance變數的初始化只要一次就好

由於所有static變數和instance變數都會自動獲得預設值,所以不必重新將它們設為預設值。

實踐38:使用基本型別(primitive types)使程式碼更快更小

使用基本型別,比使用基本型別外覆類別(wrapper),產生的程式碼又小又快。

實踐39:不要使用EnumerationIterator來巡訪Vector

巡訪Vector時,請使用get函式而非EnumerationIterator。這樣做會導致更少的函式呼叫,意味程式碼會更快。

實踐40:使用System.arraycopy() 來複製arrays

請使用System.arraycopy() 來複製arrays。那是個原生(native)函式,速度最快。

實踐41:優先使用array,然後才考慮VectorArrayList

如果可能,就使用array。如果你需要Vector的功能但不需要它的同步特性,可改用ArrayList

實踐42:儘可能復用(reuseobjects

復用現有物件,幾乎總是比產生新物件更划算。

實踐43:使用緩式評估(延遲求值,lazy evaluation

如果某個成本高貴的計算並非一定必要,就盡量少做。請使用「緩式評估」
lazy evaluation,延遲求值)技術避免那些永遠不需要的工作。

實踐44:手工優化(optimize)你的程式碼

由於Java編譯器在優化方面的作為甚少,為了生成最佳byte code,請手工優化你的原始碼。

實踐45:編譯為原生碼(native code

編譯為原生碼,通常可以導致執行速度更快的程式碼。但你卻因此必須在各種不同的原生方案(native solution)中取捨。

多緒(Multithreading

實踐46:面對instance函式,synchronized鎖定的是物件而非函式或程式碼

關鍵字synchronized鎖定的是物件,而非函式或程式碼。一個函式或程式
區段被宣告為
synchronized,並不意味同一時刻只能由一個執行緒執行它。

實踐47:弄清楚synchronized staticssynchronized instance函式之間的差異

兩個函式被宣告為synchronized,並不就意味它們是「執行緒安全」(thread-safe)的。對instance函式或object reference同步化,與對static函式或class literal(字面常數)同步化相比,得到的lock全然不同

實踐48:以「private資料搭配存取器(accessor)」取代public/protected資料 

如果沒有適當保護你的資料,用戶便有機會繞過你的同步機制。

實踐49:避免無謂的同步控制(avoid unnecessary synchronization

一般情況下請不要同步化所有函式。同步化不僅造成程式緩慢,並且喪失了
並行(
concurrency)的可能。請採用「單物件多鎖」技術以允許更多並行。

實踐50:取用共享變數時請使用synchronizedvolatile

不可切割(原子化,atomic)操作並非意味「執行緒安全」。JVM實作品被允許在私有記憶體中保留變數的工作副本。這可能會產生陳舊數值(stale values)。為避免這個問題,請使用同步化機制或將變數宣告為volatile

實踐51:在單一操作(single operation)中鎖定所有用到的objects

同步化某一函式,並不一定就會使其成為「執行緒安全」的函式碼。如果synchronized函式操控著多個objects,而它們並不都是此函式所屬classprivate instance data,那麼你必須對這些objects自身也進行同步化。

實踐52:以固定而全域性的順序取得多個locks(機鎖)以避免死結(deadlock)

當你同步化多個物件,請以固定和全域性的順序獲得locks,以避免死結。

實踐53:優先使用notifyAll()而非notify()

notify()只喚醒一個執行緒。要想喚醒多個執行緒,請使用notifyAll()

實踐54:針對wait()notifyAll()使用旋鎖(spin locks

當你等待條件變數(condition variables)時,請總是使用旋鎖(spin locks)以確保正確結果。

實踐55:使用wait()notifyAll()取代輪詢迴圈(polling loops

將所有polling loops替換為使用wait()notify()notifyAll()spin locks(旋鎖)。使用spin locks直觀而高效,使用polling loops則慢很多倍。

實踐56:不要對locked object(上鎖物件)之object reference重新賦值

當一個object被鎖定,有可能其他執行緒會因同一個object lock而受阻(blocked)。假如你對上鎖物件的object reference重新賦值,其他執行緒中懸而未決的那些locks將不再有意義。

實踐57:不要呼叫stop()suspend()

不要呼叫stop()suspend(),因為它們可能導致資料內部混亂,甚至引發死結(deadlock)。

實踐58:透過執行緒(threads)之間的合作來中止執行緒

你不應該呼叫stop()。如欲安全地停止執行緒,必須要求它們相互協作,才能姿態優雅地中止。

類別與介面(Classes and Interfaces

實踐59:使用interface支援多重繼承(multiple inheritance

當你想要支援interface的單一繼承或多重繼承,或者想要實作一個標記式的(markerinterface時,請使用interfaces

實踐60:避免interfaces中的函式發生衝突

沒有任何辦法能夠阻止兩個interfaces使用同名的常數和函式。為了避免可能的衝突,應當小心命名常數和函式。

實踐61:需要提供部分實作(partial implementation)時,請使用abstract classes

使用abstract class來為一個class提供部分實作,這些實作很可能對derived class是共通的(都被需要的)。

實踐62:區分interfaceabstract classconcrete class

一旦正確理解了interfaceabstract classconcrete class的差異,你就可以在設計和撰碼時做出正確的選擇。

實踐63:審慎地定義和實作immutable classes(恆常類別)

如果你希望object的資料永遠不被改動,請使用immutable object。這種objects自動擁有執行緒安全性(thread safety)。

實踐64:欲傳遞或接收mutable objects(可變物件)之object references時,請施行clone()

為了保證immutable objects,你必須在傳入和回傳immutable objects時對它們進行clone動作。

實踐65:使用繼承(inheritance)或委託(delegation)來定義 immutable classes(恆常類別)

使用immutable interfacecommon interfacebase class,或是immutable delegation classes,來定義immutable classes(恆常類別)。

實踐66:實作clone()時記得呼叫super.clone()

當你實作了一個clone(),總是應該呼叫super.clone()以確保產生正確的object

實踐67:別只是倚賴finalize()清理記憶體以外的(non-memory)資源

你不能保證finalize()是否被呼叫,以及何時被呼叫。因此,請專門實作一個public函式來釋放記憶體以外的資源。

實踐68:在建構式(constructors)內呼叫non-final函式時要當心

如果一個non-final函式被某個derived class覆寫,在建構式中呼叫這個函式可能會導致不可預期的結果。

 

前言
讓無知儘管信口開河吧,學習自有其價值
Let ignorance talk as it will, learning has its value.
J. de La Fontaine, The Use of Knowledge, Book viii, Fable 19

本書彙集了Java編程實踐方面的建議、忠告、範例和討論。本書的組織是一個個獨立課程,每個課程謂之實踐(PRAXIS,發音prak-sis),用以討論特定主題。每個實踐按各自獨立的方式撰寫。你可以從頭閱讀到尾,也可以挑選某些專題閱讀。這種編排風格使你可以在短暫的閒暇中閱讀此書。許多實踐都少於5頁,因此你可以在簡短的時間內學習它們。

我在這本書中詳細分析了某些設計(design)和編程(programming)方面的問題。我挑選主題的依據是編程實踐上的有效(effective)和高效(efficient)性質。Java最被人抱怨的一點是效能(效率,performance),因此我以最大的篇幅討論這一主題,探索使Java程式碼執行得更有效率的技術。

我撰寫本書,希望它能夠作為指南,幫助你設計和撰碼。它可以幫助你更全面地理解Java,讓你撰寫出更高效、更健壯和(或許最重要的是)更正確的程式碼。

本書所有資訊都適用於各種Java編程,並不囿於伺服端(server)、客戶端(client)或GUI(圖形用戶介面)編程。此外,你可以將這些資訊運用於Java的任一發行版本。

本書風格受了Scott Meyers所著的《Effective C++》和《More Effective C++》的影響。我發現他的風格對書籍組織非常有益,因此我決定採用類似的格式。

預期讀者

本書是為已經掌握Java語言基礎知識的程式員準備的。我假設讀者已經具備Java語言和並行編程(concurrent programming)的工作經驗,並理解物件導向(object-oreinted)的概念和術語。本書適用於「想獲得如何高效使用Java之實用建議、討論和範例」的程式員。

無論對Java編程老手或新手,本書都為他們提供了Java關鍵領域的資訊和討論。本書提供充足的新資訊,即使經驗豐富的程式員也能從考查他們業已熟悉的領域中獲得極大收益。例如在某些場合,我以獨特的方式討論問題,幫助程式員以不同的方法思考,或使用與以往不同的角度看待事物。

初入門的程式員也可以從本書獲益良多。我提供了討論和範例,幫助他們消除許多常見的編程錯誤。我也澄清了某些常見的Java錯誤觀念,並強調語言特性方面的某些問題。

本書組織

本書組織為六大部分。

  1. 一般技術 展現Java編程的數個基礎領域,包括引數傳遞(parameter passing),arraysVectors以及垃圾回收(garbage collection)。
  2. 物件與相等性 研究物件(objects)和基礎型別(primitive types),以及如何、為何為一個class實作equals()
  3.  
  4. 異常處理 提供異常處理技術(exception handling techniques)的細緻分析,並告訴你如何在你的程式碼中高效加入異常處理機制。
  5. 效能(效率) 展示可用來改善程式碼效能的諸多技術,並仔細審查JVMJava虛擬機器)、byte codeJITs(及時程式碼生成器)。
  6. 多執行緒 涵蓋執行緒模型(threading model)的諸多方面 它們對於建立健壯、可靠的多執行緒程式極為關鍵。
  7. 類別與介面 解釋了interfacesabstract classesconcrete classes,以及何處、何時使用它們。這部分還詳細討論了immutable object(不可變物件)、cloning(克隆、複製)和finalization(終結)。

在上述各標題之下,是數量不等的相關專題。往往我會在不止一處討論特定專題的某個屬性。例如我在不同場合討論了synchronized關鍵字的方方面面,每次討論都涉及synchronized的不同特性。為此,我提供了擴展性甚強的交叉參照,你可以由此得知何時閱讀特定專題、何處存在相關資訊。

目錄之後便是細目。這一部分包含所有實踐標題和其頁碼,並附有每個實踐的核心概要。你可以使用這個細目喚起你對專題的記憶,或用以找出某個專題。

附錄內含一個已經證實的技術,可以進一步擴展你的Java知識。之後還有一份「進一步閱讀」列表,列出關於Java、一般設計和編程方面的書籍和期刊。

三言兩語話PRAXIS(實踐)

PRAXIS(實踐)一詞,是我查詢「得以概括本書所做工作」的詞彙的結果。1982年的《American Heritage Dictionary》將PRAXIS定義為:The practical application or exercise of a branch of learning(實際應用或訓練;學習的一個支脈)。這正是我希望在本書中達成的。

最確切的恐怕是《Webster's New Collegiate Dictionary》於1958年給出的一份定義:Practice, especially of an art, science, or technical occupation; opposite to theory(實際履行,尤指藝術、科學或技術領域;與理論遙相對應)。這個定義準確概括了本書精髓。那句opposite to theory更是畫龍點睛。「理論」本身當然沒錯,但本書沒有為它準備位置。

範例程式碼

正文所列的所有程式碼,都採用本書寫作時可獲得之Java最新版本加以編譯和運行。所有程式碼都曾經在Windows NT 4.0環境下以Sun Java 2 SDKStandard Editionv1.2.1完成編譯和運行。如果你想要得到原始碼,請在以下網址進行註冊:

http://www.awl.com/cseng/register

該網頁要求你輸入一個獨一無二的碼,此碼可在本書末尾標明為「How to Register Your Book」的頁面找到。

提供反饋

歡迎讀者對本書提供相關反饋資訊。任何建議、批評或臭蟲報告,都請寄到PracticalJava@awl.com

希望本書讓你覺得有用、可讀,並且具備實用價值。

Peter Haggar
Research Triangle Park, North Carolina
November, 1999