Java 程式編碼的規範(轉)

ba發表於2007-08-16
Java 程式編碼的規範(轉)[@more@]所有的程式開發手冊都包含了各種規則。一些習慣自由程式人員可能對這些規則很不適
應,但是在多個開發人員 共同寫作的情況下,這些規則是必需的。這不僅僅是為了開
發效率來考慮,而且也是為了後期維護考慮。

命名規範
定義這個規範的目的是讓專案中所有的文件都看起來像一個人寫的,增加可讀性,減少
專案組中因為換人而帶來 的損失。(這些規範並不是一定要絕對遵守,但是一定要讓
程式有良好的可讀性)


Package 的命名
Package 的名字應該都是由一個小寫單片語成。
Class 的命名
Class 的名字必須由大寫字母開頭而其他字母都小寫的單片語成
Class 變數的命名
變數的名字必須用一個小寫字母開頭。後面的單詞用大寫字母開頭。
Static Final 變數的命名
Static Final 變數的名字應該都大寫,並且指出完整含義。
引數的命名
引數的名字必須和變數的命名規範一致。
陣列的命名
陣列應該總是用下面的方式來命名:

byte[] buffer;


而不是:

byte buffer[];



方法的引數
使用有意義的引數命名,如果可能的話,使用和要賦值的欄位一樣的名字:

SetCounter(int size){
this.size = size;
}




Java 檔案樣式
所有的 Java(*.java) 檔案都必須遵守如下的樣式規則


版權資訊
版權資訊必須在 java 檔案的開頭,比如:

/**
* Copyright ? 2000 Shanghai XXX Co. Ltd.
* All right reserved.
*/


其他不需要出現在 javadoc 的資訊也可以包含在這裡。


Package/Imports
package 行要在 import 行之前,import 中標準的包名要在本地的包名之前,而且按
照字母順序排列。如 果 import 行中包含了同一個包中的不同子目錄,則應該用 * 來
處理。

package hotlava.net.stats;

import java.io.*;
import java.util.Observable;
import hotlava.util.Application;


這裡 java.io.* 使用來代替InputStream and OutputStream 的。


Class
接下來的是類的註釋,一般是用來解釋類的。

/**
* A class representing a set of packet and byte counters
* It is observable to allow it to be watched, but only
* reports changes when the current set is complete
*/


接下來是類定義,包含了在不同的行的 extends 和 implements

public class CounterSet
extends Observable
implements Cloneable



Class Fields
接下來是類的成員變數:

/**
* Packet counters
*/
protected int[] packets;


public 的成員變數必須生成文件(JavaDoc)。proceted、private和 package 定義
的成員變數如果名字含義明 確的話,可以沒有註釋。


存取方法
接下來是類變數的存取的方法。它只是簡單的用來將類的變數賦值獲取值的話,可以簡
單的寫在一行上。

/**
* Get the counters
* @return an array containing the statistical data. This array has been
* freshly allocated and can be modified by the caller.
*/
public int[] getPackets() { return copyArray(packets, offset); }
public int[] getBytes() { return copyArray(bytes, offset); }

public int[] getPackets() { return packets; }
public void setPackets(int[] packets) { this.packets = packets; }


其它的方法不要寫在一行上


建構函式
接下來是建構函式,它應該用遞增的方式寫(比如:引數多的寫在後面)。
訪問型別 ("public", "private" 等.) 和 任何 "static", "final" 或 "synchronized"
應該在一行中,並且 方法和引數另寫一行,這樣可以使方法和引數更易讀。

public
CounterSet(int size){
this.size = size;
}



克隆方法
如果這個類是可以被克隆的,那麼下一步就是 clone 方法:

public
Object clone() {
try {
CounterSet obj = (CounterSet)super.clone();
obj.packets = (int[])packets.clone();
obj.size = size;
return obj;
}catch(CloneNotSupportedException e) {
throw new InternalError("Unexpected CloneNotSUpportedException: " + e.getMessage());
}
}



類方法
下面開始寫類的方法:

/**
* Set the packet counters
* (such as when restoring from a database)
*/
protected final
void setArray(int[] r1, int[] r2, int[] r3, int[] r4)
throws IllegalArgumentException
{
//
// Ensure the arrays are of equal size
//
if (r1.length != r2.length || r1.length != r3.length || r1.length != r4.length)
throw new IllegalArgumentException("Arrays must be of the same size");
System.arraycopy(r1, 0, r3, 0, r1.length);
System.arraycopy(r2, 0, r4, 0, r1.length);
}




toString 方法
無論如何,每一個類都應該定義 toString 方法:

public
String toString() {
String retval = "CounterSet: ";
for (int i = 0; i < data.length(); i++) {
retval += data.bytes.toString();
retval += data.packets.toString();
}
return retval;
}
}



main 方法
如果main(String[]) 方法已經定義了, 那麼它應該寫在類的底部.

程式碼編寫格式


程式碼樣式
程式碼應該用 unix 的格式,而不是 windows 的(比如:回車變成回車+換行)
文件化
必須用 javadoc 來為類生成文件。不僅因為它是標準,這也是被各種 java 編譯器都
認可的方法。使 用 @author 標記是不被推薦的,因為程式碼不應該是被個人擁有的。
縮排
縮排應該是每行2個空格. 不要在原始檔中儲存Tab字元. 在使用不同的原始碼管理工具
時Tab字元將因為使用者設 置的不同而擴充套件為不同的寬度.
如果你使用 UltrEdit 作為你的 Java 原始碼編輯器的話,你可以透過如下操作來禁止
儲存Tab字元, 方法是通 過 UltrEdit中先設定 Tab 使用的長度室2個空格,然後用
Format|Tabs to Spaces 選單將 Tab 轉換為空格。
頁寬
頁寬應該設定為80字元. 原始碼一般不會超過這個寬度, 並導致無法完整顯示, 但這一設
置也可以靈活調整. 在 任何情況下, 超長的語句應該在一個逗號或者一個運算子後折行.
一條語句折行後, 應該比原來的語句再縮排2 個字元.
{} 對
{} 中的語句應該單獨作為一行. 例如, 下面的第1行是錯誤的, 第2行是正確的:

if (i>0) { i ++ }; // 錯誤, { 和 } 在同一行

if (i>0) {
i ++
}; // 正確, { 單獨作為一行


} 語句永遠單獨作為一行.


如果 } 語句應該縮排到與其相對應的 { 那一行相對齊的位置。


括號
左括號和後一個字元之間不應該出現空格, 同樣, 右括號和前一個字元之間也不應該出
現空格. 下面的例子說明 括號和空格的錯誤及正確使用:

CallProc( AParameter ); // 錯誤
CallProc(AParameter); // 正確

不要在語句中使用無意義的括號. 括號只應該為達到某種目的而出現在原始碼中。下面
的例子說明錯誤和正確的 用法:

if ((I) = 42) { // 錯誤 - 括號毫無意義
if (I == 42) or (J == 42) then // 正確 - 的確需要括號


程式編寫規範


exit()
exit 除了在 main 中可以被呼叫外,其他的地方不應該呼叫。因為這樣做不給任何程式碼
程式碼機會來截獲退出。 一個類似後臺服務地程式不應該因為某一個庫模組決定了要退出
就退出。
異常
申明的錯誤應該丟擲一個RuntimeException或者派生的異常。
頂層的main()函式應該截獲所有的異常,並且列印(或者記錄在日誌中)在螢幕上。
垃圾收集
JAVA使用成熟的後臺垃圾收集技術來代替引用計數。但是這樣會導致一個問題:你必須在
使用完物件的例項以後 進行清場工作。比如一個prel的程式設計師可能這麼寫:

...
{
FileOutputStream fos = new FileOutputStream(projectFile);
project.save(fos, "IDE Project File");
}
...


除非輸出流一出作用域就關閉,非引用計數的程式語言,比如JAVA,是不能自動完成變
量的清場工作的。必須象 下面一樣寫:

FileOutputStream fos = new FileOutputStream(projectFile);
project.save(fos, "IDE Project File");
fos.close();



Clone
下面是一種有用的方法:

implements Cloneable

public
Object clone()
{
try {
ThisClass obj = (ThisClass)super.clone();
obj.field1 = (int[])field1.clone();
obj.field2 = field2;
return obj;
} catch(CloneNotSupportedException e) {
throw new InternalError("Unexpected CloneNotSUpportedException: " + e.getMessage());
}
}



final 類
絕對不要因為效能的原因將類定義為 final 的(除非程式的框架要求)
如果一個類還沒有準備好被繼承,最好在類文件中註明,而不要將她定義為 final 的。
這是因為沒有人可以保 證會不會由於什麼原因需要繼承她。
訪問類的成員變數
大部分的類成員變數應該定義為 protected 的來防止繼承類使用他們。
注意,要用"int[] packets",而不是"int packets[]",後一種永遠也不要用。

public void setPackets(int[] packets) { this.packets = packets; }

CounterSet(int size)
{
this.size = size;
}




程式設計技巧


byte 陣列轉換到 characters
為了將 byte 陣列轉換到 characters,你可以這麼做:

"Hello world!".getBytes();


Utility 類
Utility 類(僅僅提供方法的類)應該被申明為抽象的來防止被繼承或被初始化。


初始化
下面的程式碼是一種很好的初始化陣列的方法:

objectArguments = new Object[] { arguments };


列舉型別
JAVA 對列舉的支援不好,但是下面的程式碼是一種很有用的模板:

class Colour {
public static final Colour BLACK = new Colour(0, 0, 0);
public static final Colour RED = new Colour(0xFF, 0, 0);
public static final Colour GREEN = new Colour(0, 0xFF, 0);
public static final Colour BLUE = new Colour(0, 0, 0xFF);
public static final Colour WHITE = new Colour(0xFF, 0xFF, 0xFF);
}


這種技術實現了RED, GREEN, BLUE 等可以象其他語言的列舉型別一樣使用的常量。
他們可以用 '==' 運算子來 比較。
但是這樣使用有一個缺陷:如果一個使用者用這樣的方法來建立顏色 BLACK

new Colour(0,0,0)

那麼這就是另外一個物件,'=='運算子就會產生錯誤。她的 equal() 方法仍然有效。
由於這個原因,這個技術 的缺陷最好註明在文件中,或者只在自己的包中使用。

Swing


避免使用 AWT 元件
混合使用 AWT 和 Swing 元件
如果要將 AWT 元件和 Swing 元件混合起來使用的話,請小心使用。實際上,儘量不
要將他們混合起來使用。


滾動的 AWT 元件
AWT 元件絕對不要用 JscrollPane 類來實現滾動。滾動 AWT 元件的時候一定要用
AWT ScrollPane 元件來實 現。


避免在 InternalFrame 元件中使用 AWT 元件
儘量不要這麼做,要不然會出現不可預料的後果。


Z-Order 問題
AWT 元件總是顯示在 Swing 元件之上。當使用包含 AWT 元件的 POP-UP 選單的時候要
小心,儘量不要這樣使 用。



除錯


除錯在軟體開發中是一個很重要的部分,存在軟體生命週期的各個部分中。除錯能夠用
配置開、關是最基本 的。

很常用的一種除錯方法就是用一個 PrintStream 類成員,在沒有定義除錯流的時候就為
null,類要定義一 個 debug 方法來設定除錯用的流。



效能


在寫程式碼的時候,從頭至尾都應該考慮效能問題。這不是說時間都應該浪費在最佳化程式碼上,
而是我們時刻應該提 醒自己要注意程式碼的效率。比如:如果沒有時間來實現一個高效的
演算法,那麼我們應該在文件中記錄下來,以便 在以後有空的時候再來實現她。

不是所有的人都同意在寫程式碼的時候應該最佳化效能這個觀點的,他們認為效能最佳化的問題
應該在專案的後期再去 考慮,也就是在程式的輪廓已經實現了以後。
不必要的物件構造
不要在迴圈中構造和釋放物件


使用 StringBuffer 物件
在處理 String 的時候要儘量使用 StringBuffer 類,StringBuffer 類是構成 String 類
的基礎。String 類 將 StringBuffer 類封裝了起來,(以花費更多時間為代價)為開發
人員提供了一個安全的介面。當我們在構造 字串的時候,我們應該用 StringBuffer
來實現大部分的工作,當工作完成後將 StringBuffer 物件再轉換為 需要的 String 物件。
比如:如果有一個字串必須不斷地在其後新增許多字元來完成構造,那麼我們應該使
用 StringBuffer 物件和她的 append() 方法。如果我們用 String 物件代替 StringBuffer
物件的話,會花費 許多不必要的建立和釋放物件的 CPU 時間。

避免太多的使用 synchronized 關鍵字
避免不必要的使用關鍵字 synchronized,應該在必要的時候再使用她,這是一個避免死
鎖的好方法。

可移植性
Borland Jbulider 不喜歡 synchronized 這個關鍵字,如果你的斷點設在這些關鍵字的
作用域內的話,除錯的 時候你會發現的斷點會到處亂跳,讓你不知所措。除非必須,盡
量不要使用。


換行
如果需要換行的話,儘量用 println 來代替在字串中使用" "。
你不要這樣:

System.out.print("Hello,world! ");

要這樣:

System.out.println("Hello,world!");

或者你構造一個帶換行符的字串,至少要象這樣:

String newline = System.getProperty("line.separator");
System.out.println("Hello world" + newline);


PrintStream
PrintStream 已經被不贊成(deprecated)使用,用 PrintWrite 來代替她。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617731/viewspace-961451/,如需轉載,請註明出處,否則將追究法律責任。

相關文章