java開發規範

主要參考了阿里巴巴開發規範,特此說明java

1、通用規範

一、註釋

整體原則是: 對外接口必須寫;內部接口不建議使用 ,若是名字已經能夠解釋其意義,則不須要加註釋,若是不能解釋則能夠加數據庫

1)屬性註釋設計模式

/** xxx **/
private  String name;
2)方法裏註釋
public  void  setName(String name){
  //xxx
  do ();
}

二、文件結構

1)類的成員順序:public > private > final > static > 實例成員;類結構:成員 > 構造方法 > 靜態方法 > 實例方法api

說明:一般使用者會更關注public 屬性/方法緩存

public  class  User{
  public  final  static  String key1= 'key1' ;
  public  static  String key2= "key2" ;
  public  String key3= "key3" ;
  private  String key4= "key4" ;
  public  User(){
  }
  public  static  void  setKey3(String key3){
  }
  public  void  setKey4(String key4){
  }
  private  void  foo(){
  }
}

2)列限制:200,儘可能在一行顯示完整,超出須要換行,換行時遵循以下原則:數據結構

a 第二行相對第一行縮進 4 個空格,從第三行開始,再也不繼續縮進,參考示例。
b 運算符與下文一塊兒換行。
c 方法調用的點符號與下文一塊兒換行。併發

sb.append( "zi" ).append( "xin" )...
     .append( "huang" )...
     .append( "huang" )...
     .append( "huang" );


d 在多個參數超長,逗號後進行換行。
e 在括號前不要換行,以下反例app

method(args1, args2, args3, ...
     ,argsX);
3)縮進採用 4 個空格,禁止使用 tab 字符。(tab字符在不一樣操做系統上體現不同,能夠在ide上設置tab自動轉成4個空格)
4)字段與字段之間不換行
public  static  String name;
private  int  id;
5)方法與方法之間:換一行
public  void  method1(){
}
 
public  void  method2(){
}

三、命名規範

不能使用拼音進行命名,統一使用準確的英文進行命名框架

不採用簡寫方式命名(除公認的經常使用簡寫,或公司/小組字典表有描述)。命名過長比不能理解更好異步

1)、包名

採用單數命名。例如util,entity,service

2)、接口與類的命名

接口不要以 I 開頭。如:IUserService,而直接採用具體的命名方式如UserService

3)、抽象類命名

抽象類命名使用:Abstract+名詞的方式進行命名,如:AbstractMessage

4)、實現類命名

a 基於 SOA 的理念,暴露出來的服務必定是接口,內部的實現類用 Impl 的後綴與接口區別。例如UserServiceImpl

b 對於只有一個實現類的狀況(外部接口除外),一般先不採用接口方式,直接採用實現類便可 

c 若是有多個實現類,則採用名稱+抽象名稱+Impl,如UserMessageImpl、AdminMessageImpl

5)、變量命名

a 全部變量(描述狀態的除外)統一以準確的名詞性英文命名,名詞性英文語法以下:

  • 普通名詞,如:user、clubMember、order等
  • 組合名詞,即名詞+名詞,如:clubMemberServiceOrder,paymentResult等
  • 帶修飾語(定語)名詞,如:checkingResult,messageSendingTask(主動,用ing),closedOrder(已經關閉的訂單,用ed)

b 描述狀態的變量統一以準確的形容詞性英文命名,形容詞性英文語法以下:

  • 普通形容詞,如:active,inactive,valid,invalid等
  • 動詞轉形容詞,表示狀態,如:close > closed,stop > stopped等
  • 動詞轉形容詞,標示能動,如:delete > deletable,use > useful等

c 對於反映狀態的變量,不要在命名前面加「is」,由於自動生成的get方法,對於boolean值,方面名自動會變爲is*** 
常量用全大寫,單詞之間用「_」分割,如:

public static final String QUERYCLUBMEMBER_HQL=」…」;

d 對於成員變量,其名稱可省略所屬類的名稱,如:

public  class  User {
  private  String userName;  //NOT GOOD
  private  String name;  //GOOD
}
5)、方法命名
  • 方法名命名規則:
  1. 動詞:init,validate,pay等
  2. 動詞+介詞+(賓語):compareTo,getById等
  3. 動賓短語(表示動做):createUser,publishPrivilege
  4. 謂表短語(表示狀態):isClosed,isUserExisted,canUserBeDeleted等
  5. 接口類中的方法和屬性不要加任何修飾符號 (public 也不要加 ,保持代碼的簡潔性)

  • 單複數的使用,對於一些動做須要操做多個對象,方法名要經過名詞複數反映出來,例如:deleteOrders(刪除訂單,可能多個) 
  • 若是一個方法設計兩個動做或對象,用「And」鏈接,如:createProductAndTag,但通常狀況下,不推薦一個方法作多於一件事情 
  • 不要使用簡寫,除非是公司級別或者業界已經通用的約定或字典表定義表示 ,好比I18n,則可使用。由於簡寫很難閱讀,容易誤解,寧願方法名稍微長一些,也要讓方法名用正確的短語來表述,因爲一個方法通常不建議作多於一件事情,因此方法名通常不會太長 
  • 一些Java業界約定俗成的方法命名:
  1. 與…進行比較:compareTo
  2. 獲取單例對象:getInstance
  3. 是否相等:equals
  4. 初始化:init
  • 對於dao層,其名稱可省略所屬類的名稱,如:
public  interface  UserDao {
  int  createUser(User user);  //NOT GOOD
  int  create(User user);  //GOOD
}
6)、系統命名約定
接口、類的命名約定 
 
類名
命名
示例
Controller類 **Controller OrderController
DAO層 **Dao UserDao
Entity(領域對象) 實體名 User
Interceptor類 **Interceptor AuthenticationInterceptor
Servlet Filter類 **Filter ApplicationContextFilter
Servlet類 **Servlet SystemInitServlet
VO/DTO(視圖對象) 實體名+VO UserVO
工具類命名 ***Util DateUtil
系統監控器類 **Monitor MemcachedMonitor
邏輯層類 **Service UserService

b POJO 類命名約定

POJO類包含了Entity、VO。POJO 類中布爾類型的變量,都不要加 is ,不然部分框架解析會引發序列化錯誤。

c 常規方法的命名約定

方法名
示例
批量
備註
列表 list***(複數) listUsers - 若是返回爲空,則返回size=0的list,不能返回null
建立 create*** create createUser batchCreate**s batchCreateUsers  
刪除 delete** delete deleteUser batchDelete**s batchDeleteUsers  
更新 update** update updateUser batchUpdate**s batchUpdateUsers  
統計 count*** batchCount***  
獲取單個對象 get** get getUser batchGet**s batchGetUsers  
獲取單個對象根據某個參數 getBy** getByName -  
注:
. 若是類名已經包含一些名稱,方法和操做能夠不寫響應的名稱,例如UserDao 的方法get 而不用getUser 
. 只讀方法,不能作修改操做,例如get*** list*** paged*** search***
 
d 系統常量命名約定
  • 不要使用一個常量類維護全部常量,應該按常量功能進行歸類,分開維護。如:緩存相關的常量放在類: CacheConsts 下 ; 系統配置相關的常量放在類: ConfigConsts 下。

  說明:大而全的常量類,非得使用查找功能才能定位到修改的常量,不利於理解和維護。

  • 常量的複用層次有五層:跨應用共享常量、應用內共享常量、子工程內共享常量、包內共享常量、類內共享常量。
  1.  跨應用共享常量:放置在二方庫中,一般是 client . jar 中的 constant 目錄下。
  2. 應用內共享常量:放置在一方庫的 modules 中的 constant 目錄下。
  3. 反例:易懂變量也要統必定義成應用內共享常量,兩位攻城師在兩個類中分別定義了表示「是」的變量:
  4. 類 A 中: public static final String YES = " yes " ;
  5. 類 B 中: public static final String YES = " y " ;
  6. A . YES . equals(B . YES) ,預期是 true ,但實際返回爲 false ,致使產生線上問題。
  7. 子工程內部共享常量:即在當前子工程的 constant 目錄下。
  8. 包內共享常量:即在當前包下單獨的 constant 目錄下。
  9. 類內共享常量:直接在類內部 private static final 定義

7)、控制語句

a 在一個 switch 塊內,每一個 case 要麼經過 break / return 等來終止,要麼註釋說明程序將繼續執行到哪個 case 爲止 ; 在一個 switch 塊內,都必須包含一個 default 語句而且放在最後,即便它什麼代碼也沒有。

b 在 if / else / for / while / do 語句中必須使用大括號,即便只有一行代碼,避免使用下面的形式: if (condition) statements;

c 推薦儘可能少用 else , if - else 的方式能夠改寫成:

if  (condition) {
     ...
     return  obj;
}
邏輯上超過 3 層的 if-else 代碼可使用衛語句,或者狀態模式來實現。
衛語句就是把複雜的條件表達式拆分紅多個條件表達式,好比一個很複雜的表達式,嵌套了好幾層的if - then-else語句,轉換爲多個if語句,實現它的邏輯,這多條的if語句就是衛語句.
d 不要在條件判斷中執行其它複雜的語句,如下是正例
boolean  existed = (file.open(fileName,  "w" ) !=  null ) && (...) || (...);
if  (existed) {
     ...
}
e 循環體中的語句要考量性能
如下操做盡可能移至循環體外處理,如定義對象、變量、獲取數據庫鏈接,進行沒必要要的 try - catch 操做 ( 這個 try - catch 是否能夠移至循環體外 ) 。
f 儘可能寫無狀態的方法或者/類,如需用到值能夠經過參數方式傳遞,較少直接引用
//NOT GOOD
public  int  insertUser() {
    String name=request.get( "name" );
    String password=request.get( "password" );
}
//GOOD
public  int  insertUser(String name,String password) {
}

2、業務規範

一、全部的覆寫方法,必須加@ Override 註解。
二、不能使用過期的類或方法。
三、Object 的 equals 方法容易拋空指針異常,應使用常量或肯定有值的對象來調用equals 。
正例: " test " .equals(object);
反例: object.equals( " test " );
說明:推薦使用 java . util . Objects # equals (JDK 7 引入的工具類 )
四、全部的相同類型的包裝類對象之間值的比較,所有使用 equals 方法比較。
說明:對於 Integer var = ?在-128 至 127 之間的賦值, Integer 對象是在IntegerCache . cache 產生,會複用已有對象,這個區間內的 Integer 值能夠直接使用==進行判斷,可是這個區間以外的全部數據,都會在堆上產生,並不會複用已有對象,這是一個大坑,推薦使用 equals 方法進行判斷。
五、定義 DO / DTO / VO 等 POJO 類時,不要設定任何屬性默認值。
六、POJO 類必須寫 toString 方法。使用 IDE 的中工具: source > generate toString時,若是繼承了另外一個 POJO 類,注意在前面加一下 super . toString 。
說明:在方法執行拋出異常時,能夠直接調用 POJO 的 toString() 方法打印其屬性值,便於排查問題。
七、當一個類有多個構造方法,或者多個同名方法,這些方法應該按順序放置在一塊兒,便於閱讀。
八、類內方法定義順序依次是:公有方法或保護方法 > 私有方法 > getter / setter方法。
說明:公有方法是類的調用者和維護者最關心的方法,首屏展現最好 ; 保護方法雖然只是子類關心,也多是「模板設計模式」下的核心方法 ; 而私有方法外部通常不須要特別關心,是一個黑盒實現 ; 由於方法信息價值較低,全部 Service 和 DAO 的 getter / setter 方法放在類體最後。
九、在getter / setter 方法中,儘可能不要增長業務邏輯,增長排查問題的難度。
十、循環體內,字符串的鏈接方式,使用 StringBuilder 的 append 方法進行擴展。
十一、任何類、方法、參數、變量,嚴控訪問範圍。過寬泛的訪問範圍,不利於模塊解耦,變量做用域太大,若是無限制的處處跑,那麼你會擔憂的
十二、建立線程或線程池時請指定有意義的線程名稱,方便出錯時回溯。儘可能使用線程池,線程池須要用公共包中線程池工具進行生成。
public  class  TimerTaskThread  extends  Thread {
     public  TimerTaskThread() {
     super .setName( "TimerTaskThread" ); ...
}
1三、高併發時,同步調用應該去考量鎖的性能損耗。能用無鎖數據結構,就不要用鎖 ; 能鎖區塊,就不要鎖整個方法體 ; 能用對象鎖,就不要用類鎖。
1四、使用 CountDownLatch 進行異步轉同步操做,每一個線程退出前必須調用 countDown方法,線程執行代碼注意 catch 異常,確保 countDown 方法能夠執行,避免主線程沒法執行至 await 方法,直到超時才返回結果。
說明:注意,子線程拋出異常堆棧,不能在主線程 try - catch 到。
1五、全部的類都必須添加建立者信息
1六、方法內部單行註釋,在被註釋語句上方另起一行,使用//註釋。方法內部多行註釋使用/* */註釋,注意與代碼對齊。
1七、Java 類庫中定義的一類 RuntimeException 能夠經過預先檢查進行規避,而不該該經過 catch 來處理,好比: IndexOutOfBoundsException , NullPointerException 等等。
1八、異常不要用來作流程控制,條件控制,由於異常的處理效率比條件分支低。
1九、對大段代碼進行 try - catch ,這是不負責任的表現。 catch 時請分清穩定代碼和非穩定代碼,穩定代碼指的是不管如何不會出錯的代碼。對於非穩定代碼的 catch 儘量進行區分異常類型,再作對應的異常處理。
20、捕獲異常是爲了處理它,不要捕獲了卻什麼都不處理而拋棄之,若是不想處理它,請將該異常拋給它的調用者。最外層的業務使用者,必須處理異常,將其轉化爲用戶能夠理解的內容。
2一、對於公司外的 http / api 開放接口必須使用「錯誤碼」 ; 而應用內部推薦異常拋出 ; 跨應用間 RPC 調用優先考慮使用 Result 方式,封裝 isSuccess 、「錯誤碼」、「錯誤簡短信息」。
2二、定義時區分 unchecked / checked 異常,避免直接使用 RuntimeException 拋出,更不容許拋出 Exception 或者 Throwable ,應使用有業務含義的自定義異常。推薦業界已定義過的自定義異常,如: DAOException / ServiceException 等。
2三、一個類中有多個 public 方法,都須要進行數行相同的參數校驗操做,這個時候請抽取:private boolean checkParam(DTO dto) {...}
2四、不容許直接拿 HashMap 與 Hashtable 做爲查詢結果集的輸出。
 

3、極致函數

一、不超過100行

二、嵌套層次不超過3層

例如if else try for while等這些控制代碼的層次不能過深,不然可讀性將會變得不好。儘可能保持平級,儘早返回或跳出。

三、一個函數不超過2個功能的具體代碼,能夠是引用

若是函數內有多個功能的具體代碼,會形成臨時變量過多,而且這些變量大可能是無相關的。會形成命名困難與容易引用變量出錯。

相關文章
相關標籤/搜索