品味第一杯咖啡
一、注釋與文檔
之所以把Java注釋和文檔功能放在最前面介紹,是因為Java程式的理念使然——所謂兵馬未動糧草先行。
幾乎所有程式設計語言都提供在原始碼中添加註釋的功能,開發人員通過注釋給自己或代碼的閱讀者進行備忘或提示,好比讀書時在書上的空白處寫筆記,或在屋子裡使用N次貼。Java語言一個優秀思想便是——編寫原始碼並非唯一重要的工作,給原始碼加上詳細的注釋同樣重要。道理很簡單,原始碼和Java的位元組碼不同,位元組碼是給電腦看的,而原始碼是給人閱讀的,沒有好的文檔與注釋,閱讀原始碼必須猜測原始碼作者的意圖,勢必枯燥而且效率低下。
Java中的注釋一共有兩種,我們的Hello World!程式麻雀雖小但是五髒俱全,全部都用到了。下面是Hello World!程式的原始碼:
/*
* Created on 2004-6-4
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
/**
* @author gary chan
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class HelloWorldApp {
public static void main(String[] args) {
// 列印Hello World!字樣
System.out.println("Hello World!");
}
}
第一種注釋是從C語言繼承過來的風格,注釋從/*開始,到*/結束,它們必須成對使用,之間可以換行。Hello World!程式開頭部分就是這種風格的注釋,記載著這個來源程式的創始時間和一些提示。許多程式員為了美觀,喜歡在多行注釋前加入一個*符號,從而就形成了上面的格局。當然,這個注釋的內容是Eclipse自動產生的,你可以通過修改Eclipse的代碼模板來修改自動產生的內容。
第二種注釋是從C++語言繼承過來的單行注釋風格,注釋從//開始,一直到這行結束。這種風格的注釋非常容易使用,你不必低頭在鍵盤上連續尋找/和*鍵,只需要連續按下/鍵兩次。同時,不需要像C語言風格注釋那樣特意使注釋符號配對。Hello World!程式中“// 列印Hello World!字樣”就是這種風格的注釋。
如果你的洞察力敏銳,你會發現Hello World!程式中還有一處用/**和*/包裹起來的的代碼並不屬於以上任何一種注釋。沒錯,這是Java文檔(Java documentation)。文檔與注釋不同,注釋一般比較隨意,反映的是局部語句的功能或聲明,而文檔是與代碼的結構相關的,好比是代碼的摘要,給人一個結構化的總體觀念。特別地,Java文檔所注釋的,是緊隨其後的類、變數或方法。
我們還是結合Eclipse來說明Java文檔的應用。首先在Eclipse中開啟Hello World!程式。試試看把滑鼠移動到HelloWorldApp字元上面去,是不是顯示了1所示的效果(圖1 Eclipse自動顯示Java文檔的功能)?
沒錯,當你把滑鼠移動到一個Java類、變數或方法上,Eclipse將通過程式碼分析技術在原始碼中萃取出相應的Java文檔並且顯示給你看,如果該Java元素有文檔的話。
下面讓我們為main方法編寫Java文檔來親自體驗一下。首先把游標移動到public class HelloWorldApp {之後並斷行符號以便插入一空白行。然後,輸入/**並且斷行符號,你會發現Eclipse自動為你產生如一個Java文檔塊,並且自動識別出main方法有一個名為args的參數(很神奇吧?)。把該文檔改寫成這樣:
/**
* 這是主函數,程式將從這裡開始運行。
* @param args 命令列參數
*/
然後你把滑鼠移動到main上面,是不是得到明明白白的文檔資訊了?
實際上,Java文檔功能是貫穿於Java語言中的重要功能。但當你把游標移動到System.out.println("Hello World!")語句上,卻得不到有用的含義以及參數的用法,該語句還是Java內建的API呢。怎麼會這樣子?
聰明的你一定想到答案了——一定是Java API的Java文檔沒有配置好嘛。沒錯,J2SE SDK並不包含Java API的Java文檔,需要單獨下載。你可以從http://java.sun.com/j2se/1.4.2/download.html下載到J2SE 1.4.2的文檔,如果你從國外下載不方便,還可以到http://garychan.3322.org的Java資源欄目下載,約32.80MB。下載以後請把壓縮包中的doc目錄解壓縮到C:/j2sdk1.4.2_04/中。
Eclipse預設使用JRE作為Java虛擬機器。然而,使用J2SE SDK本身是更好的選擇,因為你可以開啟查看Java API文檔的重要功能,這對於提高軟體的開發效率以及深刻體驗Eclipse,有著重要意義。方法如下:
1.依次點擊Eclipse功能表項目中的Windows、Preferences。
2.展開Java/Installed JRE,按下Add,按照圖2所示填寫參數(圖2 完成後按下OK鍵)。
3.在Installed JREs對話方塊中的J2SDK 1.4.2_04前面打上勾,按下“OK”關閉Preferences對話方塊。Eclipse會提示你需要重新編譯一次,“OK”即可。
好了,現在把游標移動到println上看看是不是和圖3所示一樣呢(圖3)?
怎麼樣,該方法的詳細使用說明都有了吧?如果內容比較多,按下F2鎖定之後便可以察看全部的資訊。以後有什麼API不明白,不用苦苦上網搜尋了,Java API文檔本身就是Java API的大百科,再配合Eclipse的自動顯示功能,實在方便得不行。
順便說一句,Java還提供了從原始碼中自動萃取Java文檔,產生HTML檔案以便單獨閱讀的機制,那就是J2SE SDK提供的javadoc工具。在Eclipse中,可以通過File菜單中的Export選項進行操作。
Just do it
試試把HelloWorldApp的Java文檔改得更有調理,並且修改author屬性成為你的名字。然後通過Eclipse內建的javadoc輸出功能產生該項目的Java文檔,感受一下Java文檔代碼並重的開發理念。
Java文檔是一門學問。除了上面用到的param和author標籤,Java文檔還支援許多特定的標籤,可以直接內嵌HTML代碼以便得到優美的輸出,還可以通過doclets自行擴充javadoc的處理機制。完整的說明文檔請參考C:/j2sdk1.4.2_04/docs/tooldocs/windows/javadoc.html。
品味第一杯咖啡
二、類
在品味第一杯咖啡時,我們說Hello World!程式定義了一個HelloWorldApp類(class)。
類是Java等物件導向語言的基礎單位??一個定義了從類產生的執行個體(instance)中的資料和行為的關係的模板。當你執行個體化(instantiate)一個類以後便得到一個該類的對象(object),擁有類的全部資料和行為。一般我們把類和對象的資料稱為變數,把行為稱為方法。Java語言使用class關鍵詞來定義一個類,之後的一對大括弧定義了該類的變數和方法。我們的HelloWorldApp類沒有變數,只有一個main方法。
類和對象的關係很好理解??類是一個抽象概念,好比“人”,而對象是一個具體的人,比如小布希、蒲亭,他們作為人都有七情六慾(變數),都會衣食住行(方法)。
在第二篇連載《第一杯咖啡》中,為了避免類和對象的概念,我直接把HelloWorldApp稱作了對象。現在你應該明白,這個說法是不準確的,HelloWorldApp是一個類,而main是這個類的方法。現在正式撥亂反正。
品味第一杯咖啡
三、main方法
每個Java應用程式都必須包含一個main方法,文法如下:
public static void main(String[] args)
main方法包含三個修飾詞:
(1)public:表示main方法可以由任何對象調用。
(2)static:表示這是一個類方法,區別於執行個體方法,與具體的對象無關。
(3)void:表示main方法沒有傳回值。
main方法是Java語言中非常特殊的方法,類似於C/C++中的main函數。當Java解析器執行Java應用程式,它首先執行這個Java類的main方法。你應該把程式的邏輯,比如列印Hello World!字樣,寫在main裡面。
main方法有一個參數,即args,它是一個字串數組,作業系統通過這個機制傳遞命令列參數。由於Hello World!程式忽略命令列參數,所以這裡不展開討論了。
品味第一杯咖啡
四、使用類和對象
讓我們以Hello World!程式來詳細解釋類和對象的使用。
Hello World!程式很小,只定義了最基本的HelloWorldApp類。雖然如此,它的確使用了其他類??System類:
System.out.println("Hello World!");
System類是Java API的成員之一,提供了作業系統無關地操作作業系統相關功能的能力,很拗口,不過的確如此。out是System的類變數(與前面提到的類方法的意思一致)。實際上,System的所有變數都是類變數,所有方法都是類方法??都是用static修飾的,你可以通過“.”操作符直接存取。比如,System類有一個getProperty類方法可以擷取作業系統屬性,至於具體是什麼作業系統,你無需事必躬親了。若把Hello World!程式的main方法修改成:
public static void main(String[] args) {
System.out.print("Hello ");
System.out.println(System.getProperty("user.name"));
}
運行程式,便會得到“Hello Gary Chan”的結果。呵呵,我們的程式可以認人了,長大了許多啊!
下面說說類變數的原理。Java應用程式裝載System類的時候,一看到out是System的類變數,便自動初始化PrintStream類得到一個PrintStream對象,並且把這個對象賦給out變數。從而,你調用out的println方法,實際上是調用一個對象的執行個體方法。這樣,Hello World!字樣便輸出了。
總結一下類變數、類方法和執行個體變數、執行個體方法的關係:
(1)類變數或者類方法是和特定的類相關的,Java將給每個類分配一個類變數,無論這個類有多少執行個體。可以通過類名來操作類變數和類方法。
(2)執行個體變數或者執行個體方法是與特定的對象(類的執行個體)相關,每個對象都有自己專用的執行個體變數。可以通過執行個體名來操作執行個體變數和執行個體方法。
五、小結
這回我們把Hello World!程式剖析得淋漓盡致。雖然一個小小的Java程式就有那麼多門道,但是,不經曆風雨怎麼見彩虹,希望你能夠透徹感受Java語言的點滴道理,從而快速步入Java的聖堂。
不要小看Java文檔的重要性。Java有許多值得尊敬的理念,所謂沒有規矩不成方圓,你應該理解並且貫徹它,這樣才能夠寫出漂亮的代碼。