天天看點

辨別符的命名規則和規範辨別符命名規則辨別符命名規範基礎版Java代碼規範詳細版

JavaSE學習筆記整理,沒有其他用途,版權歸原作者所有,如有侵權請聯系删除。

辨別符命名規則

  1. 隻能由26個字母大小寫,數字0-9,_或$組成(不能有空格)
  2. 不能由數字開頭
  3. 不能使用關鍵字和保留字,但是能包含關鍵字和保留字
  4. 嚴格區分大小寫

辨別符命名規範基礎版

  1. 包名:多單詞組成時所有字母都小寫:aaa.bbb.ccc //比如 com.hsp.crm
  2. 類名、接口名:多單詞組成時,所有單詞的首字母大寫:XxxYyyZzz [大駝峰]

    比如: TankShotGame

  3. 變量名、方法名:多單詞組成時,第一個單詞首字母小寫,第二個單詞開始每個單詞首字母大寫:xxxYyyZzz [小駝峰,簡稱 駝峰法]

    比如: tankShotGame

  4. 常量名:所有字母都大寫。多單詞時每個單詞用下劃線連接配接:XXX_YYY_ZZZ

    比如 :定義一個所得稅率 TAX_RATE.

Java代碼規範詳細版

1. 辨別符命名規範

1.1 概述

辨別符的命名力求做到統一、達意和簡潔。

1.1.1 統一

統一是指,對于同一個概念,在程式中用同一種表示方法,比如對于供應商,既可以用supplier,也可以用provider,但是我們隻能標明一個使用,至少在一個Java項目中保持統一。統一是作為重要的,如果對同一概念有不同的表示方法,會使代碼混亂難以了解。即使不能取得好的名稱,但是隻要統一,閱讀起來也不會太困難,因為閱讀者隻要了解一次。

1.1.2 達意

達意是指,辨別符能準确的表達出它所代表的意義,比如: newSupplier, OrderPaymentGatewayService等;而 supplier1, service2,idtts等則不是好的命名方式。準确有兩成含義,一是正确,二是豐富。如果給一個代表供應商的變量起名是 order,顯然沒有正确表達。同樣的,supplier1, 遠沒有targetSupplier意義豐富。

1.1.3 簡潔

簡潔是指,在統一和達意的前提下,用盡量少的辨別符。如果不能達意,甯願不要簡潔。比如:theOrderNameOfTheTargetSupplierWhichIsTransfered 太長, transferedTargetSupplierOrderName則較好,但是transTgtSplOrdNm就不好了。省略元音的縮寫方式不要使用,我們的英語往往還沒有好到看得懂奇怪的縮寫。

1.1.4 駱駝法則

Java中,除了包名,靜态常量等特殊情況,大部分情況下辨別符使用駱駝法則,即單詞之間不使用特殊符号分割,而是通過首字母大寫來分割。比如: supplierName, addNewContract,而不是 supplier_name, add_new_contract。

1.1.5 英文 vs 拼音

盡量使用通俗易懂的英文單詞,如果不會可以向隊友求助,實在不行則使用漢語拼音,避免拼音與英文混用。比如表示歸檔,用archive比較好, 用pigeonhole則不好,用guiDang尚可接受。

1.2 包名

使用小寫字母如 com.xxx.settlment,不要 com.xxx.Settlement

單詞間不要用字元隔開,比如 com.xxx.settlment.jsfutil,而不要com.xxx.settlement.jsf_util

1.3 類名

1.3.1 首字母大寫

類名要首字母大寫,比如 SupplierService, PaymentOrderAction;不要 supplierService, paymentOrderAction.

1.3.2 字尾

類名往往用不同的字尾表達額外的意思,如下表:

字尾名 意義 舉例

Service 表明這個類是個服務類,裡面包含了給其他類提同業務服務的方法 PaymentOrderService

Impl 這個類是一個實作類,而不是接口 PaymentOrderServiceImpl

Inter 這個類是一個接口 LifeCycleInter

Dao 這個類封裝了資料通路方法 PaymentOrderDao

Action 直接處理頁面請求,管理頁面邏輯了類 UpdateOrderListAction

Listener 響應某種事件的類 PaymentSuccessListener

Event 這個類代表了某種事件 PaymentSuccessEvent

Servlet 一個Servlet PaymentCallbackServlet

Factory 生成某種對象工廠的類 PaymentOrderFactory

Adapter 用來連接配接某種以前不被支援的對象的類 DatabaseLogAdapter

Job 某種按時間運作的任務 PaymentOrderCancelJob

Wrapper 這是一個包裝類,為了給某個類提供沒有的能力 SelectableOrderListWrapper

Bean 這是一個POJO MenuStateBean

1.4 方法名

首字母小寫,如 addOrder() 不要 AddOrder()

動詞在前,如 addOrder(),不要orderAdd()

動詞字首往往表達特定的含義,如下表:

字首名 意義 舉例

create 建立 createOrder()

delete 删除 deleteOrder()

add 建立,暗示新建立的對象屬于某個集合 addPaidOrder()

remove 删除 removeOrder()

init或則initialize 初始化,暗示會做些諸如擷取資源等特殊動作 initializeObjectPool

destroy 銷毀,暗示會做些諸如釋放資源的特殊動作 destroyObjectPool

open 打開 openConnection()

close 關閉 closeConnection()<

read 讀取 readUserName()

write 寫入 writeUserName()

get 獲得 getName()

set 設定 setName()

prepare 準備 prepareOrderList()

copy 複制 copyCustomerList()

modity 修改 modifyActualTotalAmount()

calculate 數值計算 calculateCommission()

do 執行某個過程或流程 doOrderCancelJob()

dispatch 判斷程式流程轉向 dispatchUserRequest()

start 開始 startOrderProcessing()

stop 結束 stopOrderProcessing()

send 發送某個消息或事件 sendOrderPaidMessage()

receive 接受消息或時間 receiveOrderPaidMessgae()

respond 響應使用者動作 responseOrderListItemClicked()

find 查找對象 findNewSupplier()

update 更新對象 updateCommission()

find方法在業務層盡量表達業務含義,比如 findUnsettledOrders(),查詢未結算訂單,而不要findOrdersByStatus()。 資料通路層,find,update等方法可以表達要執行的sql,比如findByStatusAndSupplierIdOrderByName(Status.PAID, 345)

1.5 域(field)名

1.5.1 靜态常量

全大寫用下劃線分割,如

public static find String ORDER_PAID_EVENT = “ORDER_PAID_EVENT”;

1.5.2 枚舉

全大寫,用下劃線分割,如

public enum Events {

ORDER_PAID,

ORDER_CREATED

}

1.5.3 其他

首字母小寫,駱駝法則,如:

public String orderName;

1.6 局部變量名

參數和局部變量名首字母小寫,駱駝法則。盡量不要和域沖突,盡量表達這個變量在方法中的意義。

2. 代碼格式

用空格字元縮進源代碼,不要用tab,每個縮進4個空格。

2.1 源檔案編碼

源檔案使用utf-8編碼,結尾用unix n 分格。

2.2 行寬

行寬度不要超過80。Eclipse标準

2.3 包的導入

删除不用的導入,盡量不要使用整個包的導入。在eclipse下經常使用快捷鍵 ctrl+shift+o 修正導入。

2.4 類格式

2.5 域格式

每行隻能聲明一個域。

域的聲明用空行隔開。

2.5 方法格式

2.6 代碼塊格式

2.6.1 縮進風格

大括号的開始在代碼塊開始的行尾,閉合在和代碼塊同一縮進的行首,例如:

package com.test;
public class TestStyle extends SomeClass implements AppleInter, BananaInter {
    public static final String THIS_IS_CONST = "CONST VALUE";
    private static void main(String[] args) {
        int localVariable = 0;
    }
    public void compute(String arg) {
        if (arg.length() >  0) {
            System.out.println(arg);
        }
 
        for (int i = 0; i < 10; i++) {
              System.out.println(arg);
        }
       while (condition) {
       }
      do {
          otherMethod();
      } while (condition);
 
  switch (i) {
  case 0:
     callFunction();
     break;
  case 1:
     callFunctionb();
     break;
  default:
     break;
  }
 }
}
           

2.6.2 空格的使用

2.6.2.1 表示分割時用一個空格

不能這樣:

if       (               a >        b   )            {
    //do something here
};
           

2.6.2.2 二進制三元運算符兩邊用一個空格隔開

如下:

a + b = c;
b - d = e;
return a == b ? 1 : 0;
           

不能如下:

a+b=c;
b-d=e;
return a==b?1:0;
           

2.6.2.3 逗号語句後如不換行,緊跟一個空格

如下:

call(a, b, c);

不能如下:

call(a,b,c);

2.6.3 空行的使用

空行可以表達代碼在語義上的分割,注釋的作用範圍,等等。将類似操作,或一組操作放在一起不用空行隔開,而用空行隔開不同組的代碼, 如下:

order = orderDao.findOrderById(id);
 
//update properties
order.setUserName(userName);
order.setPrice(456);
order.setStatus(PAID);
orderService.updateTotalAmount(order);
session.saveOrUpdate(order);
           

上例中的空行,使注釋的作用域很明顯.

• 連續兩行的空行代表更大的語義分割。

• 方法之間用空行分割

• 域之間用空行分割

• 超過十行的代碼如果還不用空行分割,就會增加閱讀困難

3. 注釋規範

3.1 注釋 vs 代碼

• 注釋宜少而精,不宜多而濫,更不能誤導

• 命名達意,結構清晰, 類和方法等責任明确,往往不需要,或者隻需要很少注釋,就可以讓人讀懂;相反,代碼混亂,再多的注釋都不能彌補。是以,應當先在代碼本身下功夫。

• 不能正确表達代碼意義的注釋,隻會損害代碼的可讀性。

• 過于詳細的注釋,對顯而易見的代碼添加的注釋,羅嗦的注釋,還不如不寫。

• 注釋要和代碼同步,過多的注釋會成為開發的負擔

• 注釋不是用來管理代碼版本的,如果有代碼不要了,直接删除,svn會有記錄的,不要注釋掉,否則以後沒人知道那段注釋掉的代碼該不該删除。

3.2 Java Doc

表明類、域和方法等的意義和用法等的注釋,要以javadoc的方式來寫。Java Doc是給類的使用者來看的,主要介紹 是什麼,怎麼用等資訊。凡是類的使用者需要知道,都要用Java Doc 來寫。非Java Doc的注釋,往往是個代碼的維護者看的,着重告述讀者為什麼這樣寫,如何修改,注意什麼問題等。 如下:

/**
* This is a class comment
*/
public class TestClass {
    /**
    * This is a field comment
    */
    public String name;
    /**
    * This is a method comment
    */
    public void call() {
    }
}
           

3.3 塊級别注釋

3.3.1 塊級别注釋,單行時用 //, 多行時用

包圍

如:

/*----------start: 訂單處理 ------- */
//取得dao
OrderDao dao = Factory.getDao("OrderDao");
/* 查詢訂單 */
Order order = dao.findById(456);
//更新訂單
order.setUserName("uu");
order.setPassword("pass");
order.setPrice("ddd");
orderDao.save(order);
/*----------end: 訂單處理 ------- */
           

3.3.4 可以考慮使用大括号來表示注釋範圍

使用大括号表示注釋作用範圍的例子:

/*----------訂單處理 ------- */
{
 //取得dao
 OrderDao dao = Factory.getDao("OrderDao");
 /* 查詢訂單 */
 Order order = dao.findById(456);
 
 //更新訂單
 order.setUserName("uu");
 order.setPassword("pass");
 order.setPrice("ddd");
 
 orderDao.save(order);
}
           

3.4 行内注釋

行内注釋用 // 寫在行尾

4 最佳實踐和禁忌

4.1 每次儲存的時候,都讓你的代碼是最美的

程式員都是懶惰的,不要想着等我完成了功能,再來優化代碼的格式和結構,等真的把功能完成,很少有人會再願意回頭調整代碼。

4.2 使用log而不是System.out.println()

log可以設定級别,可以控制輸出到哪裡,容易區分是在代碼的什麼地方列印的,而System.out.print則不行。而且,System.out.print的速度很慢。是以,除非是有意的,否則,都要用log。至少在送出到svn之前把System.out.print換成log。

4.3 每個if while for等語句,都不要省略大括号{}

看下面的代碼:

if (a > b)
    a++;
           

如果在以後維護的時候,需要在a > b 時,把b++,一步小心就會寫成:

if (a > b)
    a++;
    b++;
           

這樣就錯了,因為無論a和b是什麼關系,b++都會執行。 如果一開始就這樣寫:

if (a > b)  {
    a++;
}
           

相信沒有哪個笨蛋會把b++添加錯的。而且,這個大括号使作用範圍更明顯,尤其是後面那行很長要折行時。

4.4 善用TODO:

在代碼中加入 //TODO: ,大部分的ide都會幫你提示,讓你知道你還有什麼事沒有做。比如:

if (order.isPaid()) {
    //TODO: 更新訂單
}
           

4.5 在需要留白的地方放一個空語句或注釋,告述讀者,你是故意的

比如:

if (!exists(order)) {
    ;
}
           

或:

if (!exists(order)) {
    //nothing to do
}
           

4.6 不要再對boolean值做true false判斷

比如:

if (order.isPaid() == true) {
    // Do something here
}
           

不如寫成:

if (order.isPaid()) {
    //Do something here
}
           

後者讀起來就很是 if order is paid, …. 要比 if order’s isPaid method returns true, … 更容易了解

4.7 減少代碼嵌套層次

代碼嵌套層次達3層以上時,一般人了解起來都會困難。下面的代碼是一個簡單的例子:

public void demo(int a, int b, int c) {
    if (a > b) {
        if (b > c) {
            doJobA();
        } else if (b < c) {
            doJobB()
        }
    } else {
        if (b > c) {
            if (a < c) {
                doJobC();
            }
        }
    }
}
           

減少嵌套的方法有很多:

• 合并條件

• 利用 return 以省略後面的else

• 利用子方法

比如上例,合并條件後成為:

public void demo(int a, int b, int c) {
    if (a > b && b > c) {
        doJobA();
    }
    if (a > b && c > b) {
        doJobB();
    }
    if (a <= b && c < b && a < c) {
        doJobC();
    }
}
           

如果利用return 則成為:

public void demo(int a, int b, int c) {
    if (a > b) {
        if (b > c) {
            doJobA();
            return;
        }
        doJobB()
        return;
    }
 
    if (b > c) {
        if (a < c) {
            doJobC();
        }
    }
}
           

利用子方法,就是将嵌套的程式提取出來放到另外的方法裡。

4.8 程式職責單一

關注點分離是軟體開發的真理。人類自是以能夠完成複雜的工作,就是因為人類能夠将工作分解到較小級别的任務上,在做每個任務時關注更少的東西。讓程式單元的職責單一,可以使你在編寫這段程式時關注更少的東西,進而降低難度,減少出錯。

4.9 變量的聲明,初始化和被使用盡量放到一起

比方說如下代碼:

int orderNum= getOrderNum();
//do something withou orderNum here
call(orderNum);
           

上例中的注釋處代表了一段和orderNum不相關的代碼。orderNum的聲明和初始化離被使用的地方相隔了很多行的代碼,這樣做不好,不如這樣:

//do something withou orderNum here
int orderNum= getOrderNum();
call(orderNum);
           

4.10 縮小變量的作用域

能用局部變量的,不要使用執行個體變量,能用執行個體變量的,不要使用類變量。變量的生存期越短,以為着它被誤用的機會越小,同一時刻程式員要關注的變量的狀态越少。執行個體變量和類變量預設都不是線程安全的,局部變量是線程安全的。比如如下代碼:

public class OrderPayAction{
    private Order order;
 
    public void doAction() {
        order = orderDao.findOrder();
        doJob1();
        doJob2();
    }
 
    private void doJob1() {
        doSomething(order);
    }
 
    private void doJob2() {
        doOtherThing(order);
    }
}
           

上例中order隻不過擔當了在方法間傳遞參數之用,用下面的方法更好:

public class OrderPayAction{
    public void doAction() {
        order = orderDao.findOrder();
        doJob1(order);
        doJob2(order);
    }
 
    private void doJob1(Order order) {
        doSomething(order);
    }
 
    private void doJob2(Order order) {
        doOtherThing(order);
    }
}
           

4.11 盡量不要用參數來帶回方法運算結果

比如:

public void calculate(Order order) {
    int result = 0;
    //do lots of computing and store it in the result
    order.setResult(result);
}
 
public void action() {
    order = orderDao.findOrder();
    calculate(order);
    // do lots of things about order
}
           

例子中calculate方法通過傳入的order對象來存儲結果, 不如如下寫:

public int calculate(Order order) {
    int result = 0;
    //do lots of computing and store it in the result
    return result;
}
public void action() {
    order = orderDao.findOrder();
    order.setResult(calculate(order));
    // do lots of things about order
}
           

4.12 除非有相當充足的理由,否則不許使用省略泛型類的類型參數