華為java程式碼規範
1 Java 程式設計規範
1.1 排版
1.1.1 規則
規則1 程式塊要採用縮排風格編寫,縮排的空格數為4個,不允許使用TAB縮排。
說明:縮排使程式更易閱讀,使用空格縮排可以適應不同作業系統與不同開發工具。
規則2 分界符(如大括號‘{’和‘}’)應各獨佔一行,同時與引用它們的語句左對齊。在函式體的開始、類和介面的定義、以及if、for、do、while、switch、case語句中的程式或者static、,synchronized等語句塊中都要採用如上的縮排方式。
示例: if (a>b) { doStart(); }
規則3 較長的語句、表示式或引數(>80字元)要分成多行書寫,長表示式要在低優先順序操作符處劃分新行,操作符放在新行之首,劃分出的新行要進行適當的縮排,使排版整齊,語句可讀。
示例:
if(logger.isDebugEnabled())
{
logger.debug("Session destroyed,call-id"
+event.getSession().getCallId());
}
規則4 不允許把多個短語句寫在一行中,即一行只寫一條語句
說明:閱讀程式碼更加清晰 示例:如下例子不符合規範。 Objecto = new Object(); Object b = null;
規則5 if, for, do, while, case, switch, default 等語句自佔一行,且if, for, do, while,switch等語句的執行語句無論多少都要加括號{},case 的執行語句中如果定義變數必須加括號{}。
說明:閱讀程式碼更加清晰,減少錯誤產生
示例:
if (a>b)
{
doStart();
}
case x:
{
inti = 9;
}
規則6 相對獨立的程式塊之間、變數說明之後必須加空行。
說明:閱讀程式碼更加清晰
示例:
if(a > b)
{
doStart();
}
//此處是空行
return;
規則7 在兩個以上的關鍵字、變數、常量進行對等操作時,它們之間的操作符之前、之後或者前後要加空格;進行非對等操作時,如果是關係密切的立即操作符(如.),後不應加空格。
說明:閱讀程式碼更加清晰
示例:
if (a == b)
{
objectA.doStart();
}
a *= 2;
1.1.2 建議
建議1 類屬性和類方法不要交叉放置,不同存取範圍的屬性或者方法也儘量不要交叉放置。
格式:
類定義
{
類的公有屬性定義
類的保護屬性定義
類的私有屬性定義
類的公有方法定義
類的保護方法定義
類的私有方法定義
}
建議2 修飾詞按照指定順序書寫:[訪問許可權][static][final] 。
示例:
publicstatic final String str = “abc”;
1.2 註釋
1.2.1 規則
規則1 源程式註釋量必須在30%以上。
說明:由於每個檔案的程式碼註釋不一定都可以達到30%,建議以一個系統內部模組作為單位進行檢查
規則2 包的註釋:寫入一個名為 package.html的HTML格式的說明檔案放入包所在路徑。包的註釋內容:簡述本包的作用、詳細描述本包的內容、產品模組名稱和版本、公司版權。
說明:方便JavaDoc收集,方便對包的瞭解
示例:
com/huawei/iin/websmap/comm/package.html
一句話簡述。
詳細描述。
產品模組名稱和版本
公司版權資訊
示例:
為WEBSMAP 提供通訊類,上層業務使用本包的通訊類與SMP-B 進行通訊。
詳細描述。。。。。。。。
IINV100R001 WEBSMAP
(C)版權所有 2000-2001 華為技術有限公司
規則3 類和介面的註釋放在class 或者 interface 關鍵字之前,import 關鍵字之後。註釋主要是一句話功能簡述與功能詳細描述。類註釋使用“/* /”註釋方式
說明:方便JavaDoc收集,沒有import可放在package之後。註釋可根據需要列出:作者、內容、功能、與其它類的關係等。功能詳細描述部分說明該類或者介面的功能、作用、使用方法和注意事項,每次修改後增加作者和更新版本號和日期,@since 表示從那個版本開始就有這個類或者介面,@deprecated 表示不建議使用該類或者介面。
/**
〈一句話功能簡述〉
〈功能詳細描述〉
@author [作者](必須)
- @see [相關類/方法](可選)
@since [產品/模組版本] (必須)
@deprecated (可選)
*/
示例:
packagecom.huawei.iin.logwebsmap.comm;
importjava.util.*;
/**
LogManager 類集中控制對日誌讀寫的操作。
全部為靜態變數和靜態方法,對外提供統一介面。分配對應日誌型別的讀寫器,
讀取或寫入符合條件的日誌紀錄。
@author 張三,李四,王五
- @see LogIteraotor
@see BasicLog
@since CommonLog1.0
*/
publicclass LogManager
規則4 類屬性(成員變數)、公有和保護方法註釋:寫在類屬性、公有和保護方法上面,註釋方式為“/* /”.
示例:
/**
註釋內容
*/
privateString logType;
/**
註釋內容
*/
publicvoid write()
規則5 公有和保護方法註釋內容:列出方法的一句話功能簡述、功能詳細描述、輸入引數、輸出引數、返回值、異常等。
格式:
/**
〈一句話功能簡述〉
〈功能詳細描述〉
@param [引數1] [引數1說明]
@param [引數2] [引數2說明]
@return [返回型別說明]
@exception/throws [異常型別] [異常說明]
@see [類、類#方法、類#成員]
- @since [起始版本]
@deprecated
*/
說明:@since 表示從那個版本開始就有這個方法,如果是最初版本就存在的方法無需說明;@exception或throws 列出可能仍出的異常;@deprecated 表示不建議使用該方法。
示例:
/**
* 根據日誌型別和時間讀取日誌。
* 分配對應日誌型別的LogReader, 指定型別、查詢時間段、條件和反覆器緩衝數,
* 讀取日誌記錄。查詢條件為null或0的表示沒有限制,反覆器緩衝數為0讀不到日誌。
* 查詢時間為左包含原則,即[startTime, endTime) 。
* @param logTypeName 日誌型別名(在配置檔案中定義的)
* @param startTime 查詢日誌的開始時間
* @param endTime 查詢日誌的結束時間
* @param logLevel 查詢日誌的級別
*@param userName 查詢該使用者的日誌
* @param bufferNum 日誌反覆器緩衝記錄數
* @return 結果集,日誌反覆器
* @since 1.2
*/
public static LogIterator read(StringlogType, Date startTime, Date endTime, intlogLevel, String userName, int bufferNum)
規則6 對於方法內部用throw語句丟擲的異常,必須在方法的註釋中標明,對於所呼叫的其他方法所丟擲的異常,選擇主要的在註釋中說明。 對於非RuntimeException,即throws子句宣告會丟擲的異常,必須在方法的註釋中標明。
說明:異常註釋用@exception或@throws表示,在JavaDoc中兩者等價,但推薦用@exception標註Runtime異常,@throws標註非Runtime異常。異常的註釋必須說明該異常的含義及什麼條件下丟擲該異常。
規則7 註釋應與其描述的程式碼相近,對程式碼的註釋應放在其上方,並與其上面的程式碼用空行隔開,註釋與所描述內容進行同樣的縮排。
說明:可使程式排版整齊,並方便註釋的閱讀與理解。
示例:
/*
- 註釋
*/
publicvoid example2( )
{
// 註釋
CodeBlock One
// 註釋
CodeBlock Two
}
/*
- 註釋
*/
publicvoid example( )
{
// 註釋
CodeBlock One
// 註釋
CodeBlock Two
}
規則8 對於switch語句下的case語句,必須在每個case分支結束前加上break語句。
說明:break才能真正表示該switch執行結束,不然可能會進入該case以後的分支。至於語法上合法的場景“一個case後進入下一個case處理”,應該在編碼設計上就避免。
規則9 修改程式碼同時修改相應的註釋,以保證註釋與程式碼的一致性。不再有用的註釋要刪除。
規則10 註釋的內容要清楚、明瞭,含義準確,防止註釋二義性。
說明:錯誤的註釋不但無益反而有害。
規則11 避免在註釋中使用縮寫,特別是不常用縮寫。
說明:在使用縮寫時或之前,應對縮寫進行必要的說明。
規則12 對過載父類的方法必須進行@Override宣告(5.0+)
說明:可清楚說明此方法是過載父類的方法,保證過載父類的方法時不會因為單詞寫錯而造成錯誤(寫錯方法名或者引數個數,型別都會編譯無法通過)
示例:
@Override
public voiddoRequest(SipServletRequest req) throws ServletException,
IOException
1.2.2 建議
建議1 避免在一行程式碼或表示式的中間插入註釋。
說明:除非必要,不應在程式碼或表達中間插入註釋,否則容易使程式碼可理解性變差。
建議2 在程式碼的功能、意圖層次上進行註釋,提供有用、額外的資訊。
說明:註釋的目的是解釋程式碼的目的、功能和採用的方法,提供程式碼以外的資訊,幫助讀者理解程式碼,防止沒必要的重複註釋資訊。
示例:如下注釋意義不大。
// 如果receiveFlag 為真
if(receiveFlag)
而如下的註釋則給出了額外有用的資訊。
//如果從連結收到訊息
if(receiveFlag)
建議3 對關鍵變數的定義和分支語句(條件分支、迴圈語句等)必須編寫註釋。
說明:這些語句往往是程式實現某一特定功能的關鍵,對於維護人員來說,良好的註釋幫助更好的理解程式,有時甚至優於看設計文件。
建議4 註釋應考慮程式易讀及外觀排版的因素,使用的語言若是中、英兼有的,建議多使用中文,除非能用非常流利準確的英文表達。中文註釋中需使用中文標點。方法和類描述的第一句話儘量使用簡潔明瞭的話概括一下功能,然後加以句號。接下來的部分可以詳細描述。
說明:註釋語言不統一,影響程式易讀性和外觀排版,出於對維護人員的考慮,建議使用中文。JavaDoc工具收集簡介的時候使用選取第一句話。
建議5 方法內的單行註釋使用 //。
說明:除錯程式的時候可以方便的使用/* 。。。*/ 註釋掉一長段程式。
建議6 一些複雜的程式碼需要說明。
示例:這裡主要是對閏年演算法的說明。
//1. 如果能被4整除,是閏年;
//2. 如果能被100整除,不是閏年;
//3. 如果能被400整除,是閏年。
建議7 使用Html標籤使JavaDoc生成更加美觀。
示例:
/**
* Returns a hash code for this string. Thehash code for a
* <code>String</code> objectis computed as
* <blockquote><pre>
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... +s[n-1]
* </pre></blockquote>
* using <code>int</code>arithmetic, where <code>s[i]</code> is the
* <i>i</i>th character of thestring, <code>n</code> is the length * of
* the string, and<code>^</code> indicates exponentiation.
* (The hash value of the empty string iszero.)
*
* @return a hash code value for this object.
*/
public int hashCode()
生成後的JavaDoc
圖1 生成後的JavaDoc
1.3 命名
1.3.1 規則
規則1 類名和介面使用類意義完整的英文描述,每個英文單詞的首字母使用大寫、其餘字母使用小寫的大小寫混合法。
示例:OrderInformation,CustomerList, LogManager, LogConfig, SmpTransaction
規則2 方法名使用類意義完整的英文描述:第一個單詞的字母使用小寫、剩餘單詞首字母大寫其餘字母小寫的大小寫混合法。
示例:
privatevoid calculateRate();
publicvoid addNewOrder();
規則3 方法中,存取屬性的方法採用setter 和 getter方法,動作方法採用動詞和動賓結構。
格式:
get + 非布林屬性名()
is + 布林屬性名()
set + 屬性名()
動詞()
動詞 + 賓語()
示例:
publicString getType();
publicboolean isFinished();
publicvoid setVisible(boolean);
publicvoid show();
publicvoid addKeyListener(Listener);
規則4 屬性名使用意義完整的英文描述,第一個單詞的字母使用小寫,剩餘單詞首字母大寫其餘字母小寫的大小寫混合法。屬性名不能與方法名相同。
示例:
privatecustomerName;
privateorderNumber;
privatesmpSession;
規則5 常量名使用全大寫的英文描述,英文單詞之間用下劃線分隔開,並且使用 static final修飾。
示例:
publicstatic final int MAX_VALUE = 1000;
publicstatic final String DEFAULT_START_DATE = “2001-12-08”;
1.3.2 建議
建議1 包名採用域字尾倒置的加上自定義的包名,採用小寫字母,都應該以com.huawei開頭(不包括一些特殊原因)。在部門內部應該規劃好包名的範圍,防止產生衝突。部門內部產品使用部門的名稱加上模組名稱。產品線的產品使用產品的名稱加上模組的名稱。
說明:除特殊原因包結構都必須以com.huawei開頭,如果因為OEM合作等關係,可以不做要求。
格式:
com.huawei.產品名.模組名稱
示例:
融合WEBSMAP包名 com.huawei.iin.websmap
建議2 通過對函式或過程、變數、結構等正確的命名以及合理地組織程式碼的結構,使程式碼成為自注釋的。
說明:清晰準確的函式、變數等的命名,可增加程式碼可讀性,並減少不必要的註釋。
建議3 常用元件類的命名以元件名加上元件型別名結尾。
示例:
Application 型別的,命名以App 結尾——MainApp
Frame 型別的,命名以Frame 結尾——TopoFrame
Panel 型別的,建議命名以Panel結尾——CreateCircuitPanel
Bean 型別的,建議命名以Bean 結尾——DataAccessBean
EJB 型別的,建議命名以EJB 結尾——DBProxyEJB
Applet 型別的,建議命名以Applet 結尾——PictureShowApplet
建議4 如果函式名超過15 個字母,可採用以去掉母音字母的方法或者以行業內約定俗成的縮寫方式縮寫函式名。
示例:
getCustomerInformation() 改為 getCustomerInfo()
建議5 準確地確定成員函式的存取控制符號:只是該類內部呼叫的函式使用 private 屬性,繼承類可以使用的使用protected屬性,同包類可以呼叫的使用預設屬性(不加屬性控制符號),對外公開的函式使用public屬性
示例:
protected void getUserName()
{
。。。。。。
}
private void calculateRate()
{
。。。。。。
}
建議6 含有集合意義的屬性命名,儘量包含其複數的意義。
示例:
customers, orderItems
1.4 編碼
1.4.1 規則
規則1 資料庫操作、IO操作等需要使用結束close()的物件必須在try -catch-finally 的finally中close(),如果有多個IO物件需要close(),需要分別對每個物件的close()方法進行try-catch,防止一個IO物件關閉失敗其他IO物件都未關閉。
示例:
try
{
// ... ...
}
catch(IOExceptionioe)
{
//... ...
}
finally
{
try
{
out.close();
}
catch (IOException ioe)
{
//... ...
}
try
{
in.close();
}
catch (IOException ioe)
{
//... ...
}
}
規則2 系統非正常執行產生的異常捕獲後,如果不對該異常進行處理,則應該記錄日誌。
說明:此規則指通常的系統非正常執行產生的異常,不包括一些基於異常的設計。若有特殊原因必須用註釋加以說明。
示例:
try
{
//.... ...
}
catch(IOException ioe)
{
logger.error(ioe);
}
規則3 自己丟擲的異常必須要填寫詳細的描述資訊。
說明:便於問題定位。
示例:
thrownew IOException(“Writing dataerror! Data: ” + data.toString());
規則4 執行時異常使用RuntimeException的子類來表示,不用在可能丟擲異常的方法宣告上加throws子句。非執行期異常是從Exception繼承而來的,必須在方法宣告上加throws子句。
說明:
非執行期異常是由外界執行環境決定異常丟擲條件的異常,例如檔案操作,可能受許可權、磁碟空間大小的影響而失敗,這種異常是程式本身無法避免的,需要呼叫者明確考慮該異常出現時該如何處理方法,因此非執行期異常必須有throws子句標出,不標出或者呼叫者不捕獲該型別異常都會導致編譯失敗,從而防止程式設計師本身疏忽。
執行期異常是程式在執行過程中本身考慮不周導致的異常,例如傳入錯誤的引數等。丟擲執行期異常的目的是防止異常擴散,導致定位困難。因此在做異常體系設計時要根據錯誤的性質合理選擇自定義異常的繼承關係。
還有一種異常是Error 繼承而來的,這種異常由虛擬機器自己維護,表示發生了致命錯誤,程式無法繼續執行例如記憶體不足。我們自己的程式不應該捕獲這種異常,並且也不應該建立該種類型的異常。
規則5 在程式中使用異常處理還是使用錯誤返回碼處理,根據是否有利於程式結構來確定,並且異常和錯誤碼不應該混合使用,推薦使用異常。
說明:
一個系統或者模組應該統一規劃異常型別和返回碼的含義。
但是不能用異常來做一般流程處理的方式,不要過多地使用異常,異常的處理效率比條件分支低,而且異常的跳轉流程難以預測。
注意:Java 5.0 程式內部的錯誤碼可以使用列舉來表示。
規則6 注意運算子的優先順序,並用括號明確表示式的操作順序,避免使用預設優先順序。
說明:防止閱讀程式時產生誤解,防止因預設的優先順序與設計思想不符而導致程式出錯。
示例:
下列語句中的表示式
word= (high << 8) | low (1)
if((a | b) && (a & c)) (2)
if((a | b) < (c & d)) (3)
如果書寫為
high<< 8 | low
a | b&& a & c
a | b< c & d
(1)(2)雖然不會出錯,但語句不易理解;(3)造成了判斷條件出錯。
規則7 避免使用不易理解的數字,用有意義的標識來替代。涉及物理狀態或者含有物理意義的常量,不應直接使用數字,必須用有意義的靜態變數或者列舉來代替。使用異常來表示方法執行錯誤,而不是使用C++的錯誤返回碼方式。
示例:如下的程式可讀性差。
if(state == 0)
{
state = 1;
... // program code
}
應改為如下形式:
privatefinal static int TRUNK_IDLE = 0;
privatefinal static int TRUNK_BUSY = 1;
privatefinal static int TRUNK_UNKNOWN = -1;
if(state == TRUNK_IDLE)
{
state = TRUNK_BUSY;
... // program code
}
注意:Java5.0 下建議使用列舉來表示。
異常:
publicvoid function()
{
…
throw new RuntimeException(“。。。”);
}
規則8 陣列宣告的時候使用 int[] index ,而不要使用 int index[] 。
說明:使用int index[] 格式使程式的可讀性較差,int [] index 表示聲明瞭一個int陣列(int [])叫做index
示例:
如下程式可讀性差:
publicint getIndex()[]
{
....
}
如下程式可讀性好:
publicint[] getIndex()
{
....
}
規則9 不要使用 System.out 與 System.err 進行控制檯列印,應該使用工具類(如:日誌工具)進行統一記錄或者列印。
說明:程式碼釋出的時候可以統一關閉控制檯列印,程式碼除錯的時候又可以開啟控制檯列印,方便除錯。
規則10 用調測開關來切換軟體的DEBUG版和正式版,而不要同時存在正式版本和DEBUG版本的不同原始檔,以減少維護的難度。
規則11 集合必須指定模板型別(5.0+)
說明:方便程式閱讀,除去強制轉換程式碼
示例:
Map