java 編程規範
1. 應用範圍
本規範應用於采用J2EE規範的項目中,所有項目中的JAVA代碼(含JSP,SERVLET,JAVABEAN,EJB)均應遵守這個規範。同時,也可作為其它項目的參考。
2. 設計類和方法
2.1 創建具有很強內聚力的類
方法的重要性往往比類的重要性更容易理解,方法是指執行一個統一函數的一段代碼。類常被錯誤的視為是一個僅僅用於存放方法的容器。有些開發人員甚至把這種思路作了進一步的發揮,將他們的所有方法放入單個類之中。
之所以不能正確的認識類的功能,原因之一是類的實現實際上並不影響程序的執行。當一個工程被編譯時,如果所有方法都放在單個類中或者放在幾十個類中,這沒有任何關系。雖然類的數量對代碼的執行並無太大的影響,但是當創建便於調試和維護的代碼時,類的數量有時會帶來很大的影響。
類應該用來將相關的方法組織在一起。
當類包含一組緊密關聯的方法時,該類可以說具有強大的內聚力。當類包含許多互不相關的方法時,該類便具有較弱的內聚力。應該努力創建內聚力比較強的類。
大多數工程都包含許多並不十分適合與其他方法組合在一起的方法。在這種情況下,可以為這些不合群的方法創建一個綜合性收容類。
創建類時,應知道“模塊化”這個術語的含義是什麽。類的基本目的是創建相當獨立的程序單元。
2.2 創建松散連接和高度專用的方法
1. 使所有方法都執行專門的任務
每個方法都應執行一項特定的任務,它應出色的完成這項任務。應避免創建執行許多不同任務的方法。
創建專用方法有許多好處。首先調試將變得更加容易。
2. 盡量使方法成為自成一體的獨立方法
當一個方法依賴於其他方法的調用時,稱為與其他方法緊密連接的方法。緊密連接的方法會使調試和修改變得比較困難,因為它牽涉到更多的因素。松散連接的方法優於緊密連接的方法,但你不可能使每個方法都成為獨立的方法。
若要使方法具備較強的獨立性,方法之一是盡量減少類變量。
創建方法時,設法將每個方法視為一個黑箱,其他例程不應要求了解該方法的內部工作情況,該方法也不應要求了解它外面的工程情況。這就是為什麽你的方法應依靠參數而不應依靠全局變量的原因。
創建專用方法時,請考慮下列指導原則:
1) 將復雜進程放入專用方法。如果應用程序使用復雜的數學公式,請考慮將每個公式放入它自己的方法中。這樣使用這些公式的其他方法就不包含用於該公式的實際代碼。這樣也可以更容易發現與公式相關的問題。
2) 將數據輸入/輸出(I/O)放入專用方法。
3) 將專用方法中可能要修改的代碼隔離。如果你知道某個進程經常變更,請將這個多變的代碼放入專用方法,以便以後可以更容易的進行修改,並減少無意中給其他進程帶來問題的可能性。
4) 將業務規則封裝在專用方法中。業務規則常屬於要修改的代碼類別,應與應用程序的其余部分隔開。其他方法不應知道業務規則,只有要調用的方法才使用這些規則。
3. 設計類和方法時,要達到下列目的:
1) 創建更加容易調試和維護的方法
2) 創建具有強大內聚力的類
3) 創建高度專用的方法
4) 創建松散連接的方法
5) 盡量使方法具有獨立性
6) 提高方法的扇入性
7) 降低方法的扇出性
2.3 編程原則
1. 為方法和類賦予表義性強的名字
為了使代碼更加容易理解,最容易的方法之一是為你的方法賦予表義性強的名字。函數名DoIt、GetIt的可讀性很難與CalculateSalesTax、 RetrieveUserID相比。
由縮寫方法名組成的代碼很難理解和維護,沒有理由再這樣做了。
給方法正確的命名,可使程序工程的調試和維護工作大大的改觀。請認真對待方法命名的工作,不要為了減少鍵入操作量而降低方法的可理解度。
實際應用舉例:
1) 給方法命名時應大小寫字母混合使用。如果句子全使用大寫字母,那麽閱讀起來就非常困難,而大小寫字母混合使用的句子,閱讀起來就很容易。
2) 定義方法名時不要使用縮寫。如果你認為應用程序中的某些工程應使用縮寫,那麽請將這些情況加上註釋,並確保每個人在所有時間內都使用這些縮寫。決不要在某些方法中對某些單詞進行縮寫,而在別的方法中卻不使用縮寫。
2. 為每個方法賦予單個退出點
3. 創建方法時,始終都應顯式地定義它的作用域。
1) 如果你真的想創建一個公用方法,請向代碼閱讀者說明這一點。
2) 通過為每個方法賦予一個明確定義的作用域,可以減少代碼閱讀者需要投入的工作量。應確保你為方法賦予最有意義的作用域。如果一個方法只被同一類中的另一個方法調用,那麽請將它創建成私有方法。如果該方法是從多個類中的多個方法中調用,請將該說明為公用方法。
4. 用參數在方法之間傳遞數據
應盡量避免使用類變量。一般來說,變量的作用域越小越好。為了減少類變量,方法之一是將數據作為參數在不同方法之間傳遞,而不是讓方法共享類變量。
1) 為每個參數指定數據類型。
2)
始終要對數進行檢驗,決不要假設你得數據沒有問題。程序員常犯的一個錯誤是在編寫方法時假設數據沒有問題。在初始編程階段,當編寫調用方法時,這樣的假設並無大礙。這時你完全能夠知道什麽是參數的許可值,並按要求提供這些值。但如果你不對參數的數據進行檢驗,那麽下列情況就會給你帶來很大麻煩:另外某個人創建了一個調用方法,但此人不知道允許的值;你在晚些時候添加了新的調用方法,並錯誤的傳遞了壞數據。
3. 命名約定
所有變量的定義應該遵循匈牙利命名法,它使用3字符前綴來表示數據類型,3個字符的前綴必須小寫,前綴後面是由表意性強的一個單詞或多個單詞組成的名字,而且每個單詞的首寫字母大寫,其它字母小寫,這樣保證了對變量名能夠進行正確的斷句。
這樣,在一個變量名就可以反映出變量類型和變量所存儲的值的意義兩方面內容,這使得代碼語句可讀性強、更加容易理解。
3.1 包、類及方法命名
標示符類型
命名約定
例子
包
l 全部小寫。
l 標識符用點號分隔開來。為了使包的名字更易讀,Sun 公司建議包名中的標識符用點號來分隔。
l Sun 公司的標準 java 分配包用標識符 .java 開頭。
l 全局包的名字用你的機構的 Internet 保留域名開頭 。
局部包:
interface.screens
全局包:
com.rational.www. interface.screens
類,接口
l 類的名字應該使用名詞。
l 每個單詞第一個字母應該大寫。
l 避免使用單詞的縮寫,除非它的縮寫已經廣為人知,如HTTP。
Class Hello ;
Class HelloWorld ;
Interface Apple ;
方法
l 第一個單詞一般是動詞。
l 第一個字母是小些,但是中間單詞的第一個字母是大寫。
l 如果方法返回一個成員變量的值,方法名一般為get+成員變量名,如若返回的值是bool變量,一般以is作為前綴。
l 如果方法修改一個成員變量的值,方法名一般為:set + 成員變量名。
getName();
setName();
isFirst();
變量
l 第一個字母小寫,中間單詞的第一個字母大寫。
l 不要用_或&作為第一個字母。
l 盡量使用短而且具有意義的單詞。
l 單字符的變量名一般只用於生命期非常短暫的變量。i,j,k,m,n一般用於integers;c,d,e一般用於characters。
l 如果變量是集合,則變量名應用復數。
l 命名組件采用匈牙利命名法,所有前綴均應遵循同一個組件名稱縮寫列表。
String myName;
int[] students;
int i;
int n;
char c;
btNew;
(bt是Button的縮寫)
常量
l 所有常量名均全部大寫,單詞間以‘_’隔開。
int MAX_NUM;
3.2 其它
開發人員如果遇到上述表格中未列舉的類型,請書面通知相關管理人員,由管理人員集中更新列表內容,不得擅自啟用未經確定的新變量前綴。
4. 使用常量
4.1 使用常量
1. 常數很容易在數據輸入時出錯
常數存在的主要問題之一是你很容易在鍵入數字時出錯,從而顛倒了數字的位置。例如,當你鍵入數字10876時,很容易的鍵入10867或18076。與處理變量和保留字的方法不同,編譯器並不在乎顛倒了位置和不正確的數字,有時簡單的錯誤造成的問題不會立即表現出來,而當問題表現出來時,它們會以隨機的計算錯誤的形式出現,這些錯誤很難準確定位。用常量來取代常數時,編譯器將在編譯時檢查常量的有效性。如果常量不存在,編譯器便將這一情況通知你,並拒絕進行編譯,這可以消除錯誤鍵入的數字帶來的問題,只要常量擁有正確的值,使用該常量的所有代碼也有使用該正確值。
2. 常數很難不斷更新
3. 常量使代碼更容易閱讀
使用常量後,得到的一個額外好處是可使創建的代碼更容易閱讀。常數很不直觀。也許你對常數非常了解,但其他人則根本看不明白。通過合理的給常量命名,使用這些常量的代碼就變得比較直觀了,更容易閱讀。
為常量賦予較寬的作用域,這與使用變量時的情況不同。在一個應用程序中你決不應該兩次創建相同的常量。如果你發現自己復制了一個常量,請將原始的常量說明轉至較寬的作用域,直到該常量可供引用它的所有方法為止。
5. 變量
5.1 定義有焦點的變量
用於多個目的的變量稱為無焦點(多焦點)的變量。無焦點變量所代表的意義與程序的執行流程有關,當程序處於不同位置時,它所表示的意義是不固定的,這樣就給程序的可讀性和可維護性帶來了麻煩。
5.2 只對常用變量名和長變量名進行縮寫
如果需要對變量名進行縮寫時,一定要註意整個代碼中縮寫規則的一致性。例如,如果在代碼的某些區域中使用Cnt,而在另一些區域中又使用Count,就會給代碼增加不必要的復雜性。
變量名中盡量不要出現縮寫。
5.3 使用統一的量詞
通過在結尾處放置一個量詞,就可創建更加統一的變量,它們更容易理解,也更容易搜索。例如,請使用strCustomerFirst和strCustomerLast,而不要使用strFirstCustomer和strLastCustomer。
量詞列表:
量詞後綴
說明
First
一組變量中的第一個
Last
一組變量中的最後一個
Next
一組變量中的下一個變量
Prev
一組變量中的上一個
Cur
一組變量中的當前變量
5.4 使用肯定形式的布爾變量
給布爾變量命名時,始終都要使用變量的肯定形式,以減少其它開發人員在理解布爾變量所代表的意義時的難度。
5.5 為每個變量選擇最佳的數據類型
這樣即能減少對內存的需求量,加快代碼的執行速度,又會降低出錯的可能性。用於變量的數據類型可能會影響該變量進行計算所產生的結果。在這種情況下,編譯器不會產生運行期錯誤,它只是迫使該值符合數據類型的要求。這類問題極難查找。
5.6 盡量縮小變量的作用域
如果變量的作用域大於它應有的範圍,變量可繼續存在,並且在不再需要該變量後的很長時間內仍然占用資源。
它們的主要問題是,任何類中的任何方法都能對它們進行修改,並且很難跟蹤究竟是何處進行修改的。
占用資源是作用域涉及的一個重要問題。對變量來說,盡量縮小作用域將會對應用程序的可靠性產生巨大的影響。
6. 代碼的格式化
6.1 對代碼進行格式化時,要達到的目的
1. 通過代碼分割成功能塊和便於理解的代碼段,使代碼更容易閱讀和理解;
2.
使用空行和註釋行,將程序中邏輯上不相關的代碼塊分開。比如:變量聲明部分和代碼語句間的分隔;較長的方法中,完成不同功能的代碼塊間的分隔。要避免出現邏輯上混亂的分隔,如:某一邏輯功能代碼塊中間用空行進行了分隔,但是在相鄰功能代碼塊之間卻沒有分隔,這樣會給程序閱讀者造成錯覺。
3. 減少為理解代碼結構而需要做的工作;
4. 使代碼的閱讀者不必進行假設;
5. 使代碼結構盡可能做到格式清楚明了。
6.2 編程原則
1. 要將多個語句放在同一行上
不論是變量聲明,還是語句都不要在一行上書寫多個。
2. 縮進後續行
當你將變量設置為某個值時,所有後續行的縮進位置應與第一行的變量值相同;
當你調用一個方法時,後續行縮進到第一個參數的開始處;
當你將變量或屬性設置為等於表達式的計算結果時,請從後面分割該語句,以確保該表達式盡可能放在同一行上。
3. 在if語句後縮進;
在else語句後縮進
在switch語句後縮進
在case語句後縮進
在do句後縮進
已經用行接續符分割的語句的各個行要縮進
對從屬於行標註的代碼進行縮進。
4. 在執行統一任務的各個語句組之間插入一個空行。好的代碼應由按邏輯順序排列的進程或相關語句組構成。
7. 代碼的註釋
7.1 使用代碼註釋的目的
1. 文字說明代碼的作用(即為什麽要用編寫該代碼,而不是如何編寫);
2. 確指出該代碼的編寫思路和邏輯方法;
3. 人們註意到代碼中的重要轉折點;
4. 使代碼的閱讀者不必在他們的頭腦中仿真運行代碼的執行方法.
7.2 編程原則
1. 用文字說明代碼的作用:
簡單的重復代碼做寫什麽,這樣的註釋幾乎不能給註釋增加什麽信息.如果你使用好的命名方法來創建直觀明了的代碼那麽這些類型的註釋絕對增加不了什麽信息.
2. 如果你想違背好的編程原則,請說明為什麽
有的時候你可能需要違背好的編程原則,或者使用了某些不正規的方法,.遇到這種情況時,請用內部註釋來說明你在做什麽和為什麽要這樣做。
技巧性特別高的代碼段,一定要加詳細的註釋,不要讓其他開發人員花很長時間來研究一個高技巧但不易理解的程序段。
3. 用註釋來說明何時可能出錯和為什麽出錯
4. 在編寫代碼前進行註釋
給代碼加註釋的方法之一是在編寫一個方法前首先寫上註釋.如果你願意,可以編寫完整句子的註釋或偽代碼.一旦你用註釋對代碼進行了概述,就可以在註釋之間編寫代碼.
5. 在要註釋的代碼前書寫註釋
註釋一定出現在要註釋的程序段前,不要在某段程序後書寫對這段程序的註釋,先看到註釋對程序的理解會有一定幫助。
如果有可能,請在註釋行與上面代碼間加一空行。
6. 純色字符註釋行只用於主要註釋
註釋中要分隔時,請使用一行空註釋行來完成,不要使用純色字符,以保持版面的整潔、清晰。
7. 避免形成註釋框
用星號圍成的註釋框,右邊的星號看起來很好,但它們給註釋增加了任何信息嗎?實際上這會給編寫或編輯註釋的人增加許多工作。
8. 增強註釋的可讀性
註釋是供人閱讀的,而不是讓計算機閱讀的。
1) 使用完整的語句。雖然不必將註釋分成段落(最好也不要分成段落),但你應盡量將註釋寫成完整的句子。
2) 避免使用縮寫。縮寫常使註釋更難閱讀,人們常用不同的方法對相同的單詞進行縮寫,這會造成許多混亂,如果必須對詞匯縮寫,必須做到統一。
3) 將整個單詞大寫,以突出它們的重要性。若要使人們註意註釋中的一個或多個單詞,請全部使用大寫字母。
9. 對註釋進行縮進,使之與後隨的語句對齊。
註釋通常位於它們要說明的代碼的前面。為了從視覺上突出註釋與它的代碼之間的關系,請將註釋縮進,使之與代碼處於同一個層次上。
10. 為每個方法賦予一個註釋標頭
每個方法都應有一個註釋標頭。方法的註釋標頭可包含多個文字項,比如輸入參數、返回值、原始作者、最後編輯該方法的程序員、上次修改日期、版權信息。
11. 當行尾註釋用在上面這種代碼段結構中時,它們會使代碼更難閱讀。
使用多個行尾註釋時(比如用於方法頂部的多個變量說明),應使它們互相對齊。這可使它們稍容易閱讀一些。
12. 何時書寫註釋
1) 請在每個if語句的前面加上註釋。
2) 在每個switch語句的前面加上註釋。與if語句一樣,switch語句用於評估對程序執行產生影響的表達式。
3) 在每個循環的前面加上註釋。每個循環都有它的作用,許多情況下這個作用不清楚直觀。
7.3 註釋那些部分
項目
註釋哪些部分
實參/
參數
參數類型
參數用來做什麽
任何約束或前提條件
示例
字段/
字段/屬性
字段描述
註釋所有使用的不變量
示例
並行事件
可見性決策
類
類的目的
已知的問題
類的開發/維護歷史
註釋出采用的不變量
並行策略
編譯單元
每一個類/類內定義的接口,含簡單的說明
文件名和/或標識信息
版權信息
接口
目的
它應如何被使用以及如何不被使用
局部變量
用處/目的
成員函數註釋
成員函數做什麽以及它為什麽做這個
哪些參數必須傳遞給一個成員函數
成員函數返回什麽
已知的問題
任何由某個成員函數拋出的異常
可見性決策
成員函數是如何改變對象的
包含任何修改代碼的歷史
如何在適當情況下調用成員函數的例子適用的前提條件和後置條件
成員函數內部註釋
控制結構
代碼做了些什麽以及為什麽這樣做
局部變量
難或復雜的代碼
處理順序
7.4 示例
7.4.1 塊註釋:
主要用來描述文件,類,方法,算法等。一般用在文檔和方法的前面,也可以放在文檔的任何地方。以‘/*’開頭,‘*/’結尾。例:
……
/*
* 註釋
*/
……
7.4.2 行註釋:
主要用在方法內部,對代碼,變量,流程等進行說明。與塊註釋格式相似,但是整個註釋占據一行。例:
……
/* 註釋 */
……
7.4.3 尾隨註釋:
與行註釋功能相似,放在代碼的同行,但是要與代碼之間有足夠的空間,便於分清。例:
int m=4 ; /* 註釋 */
如果一個程序塊內有多個尾隨註釋,每個註釋的縮進應該保持一致。
7.4.4 行尾註釋:
與行註釋功能相似,放在每行的最後,或者占據一行。以‘//’開頭。
7.4.5 文檔註釋:
與塊註釋相似,但是可以被javadoc處理,生成HTML文件。以‘/**’開頭,‘*/’結尾。文檔註釋不能放在方法或程序塊內。例:
/**
註釋
*/
8. 表達式和語句
8.1 每行應該只有一條語句。
8.2 if-else,if-elseif語句,任何情況下,都應該有“{”,“}”,格式如下:
if (condition) {
statements;
} else if (condition) {
statements;
} else{
statements;
}
8.3 for語句格式如下:
for (initialization; condition; update) {
statements;
}
如果語句為空:
for (initialization; condition; update) ;
8.4 while語句格式如下:
while (condition) {
statements;
}
如果語句為空:
while (condition);
8.5 do-while語句格式如下:
do {
statements;
} while (condition);
8.6 switch語句,每個switch裏都應包含default子語句,格式如下:
switch (condition) {
case ABC:
statements;
/* falls through */
case DEF:
statements;
break;
case XYZ:
statements;
break;
default:
statements;
break;
}
8.7 try-catch語句格式如下:
try {
statements;
} catch (ExceptionClass e) {
statements;
} finally {
statements;
}
9. 錯誤處理和異常事件
通常的思想是只對錯誤采用異常處理:邏輯和編程錯誤,設置錯誤,被破壞的數據,資源耗盡,等等。
通常的法則是系統在正常狀態下以及無重載和硬件失效狀態下,不應產生任何異常。異常處理時可以采用適當的日誌機制來報告異常,包括異常發生的時刻。不要使用異常實現來控制程序流程結構。
10. 封裝、事務
1. 非商務公用組件單獨封裝
2. 每一個業務流程單獨封裝
3. 一次方法(組件)的調用應能完成某一項功能或流程,即符合完整性
4. 一次方法(組件)的調用符合ACID事務性
5. 多次方法(組件)的調用應包含在一個事務中
11. 可移植性
1. 盡量不要使用已經被標為不贊成使用的類或方法。
2. 如果需要換行的話,盡量用 println 來代替在字符串中使用"\n"。
3. 用separator()方法代替路徑中的”/”或”\” 。
4. 用pathSeptarator()方法代替路徑中的 ” : ” 或 ” ;” 。
java 編程規範