阿里Java 開發(fā)手冊(cè) 筆記

編程規(guī)約


命名規(guī)范

變量命名不使用拼音。

領(lǐng)域模型相關(guān)命名使用全大寫。
UserDo,UserDTO

常量名使用全大寫,下劃線分開,盡量表達(dá)清除。
MAX_STOCK_COUNT

抽象類以Abstract或者Base開頭。
BaseDAO

異常類名以Exception結(jié)尾。

測(cè)試類以它要測(cè)試的類的名稱開始,Test結(jié)尾。
UserServiceTest

POJO中,布爾類型變量名不要加is,某些框架會(huì)引起序列化錯(cuò)誤。

包名統(tǒng)一小寫、單數(shù),類名如Utils可以復(fù)數(shù)。

接口方法不加修飾符號(hào)。

將設(shè)計(jì)模式體現(xiàn)在類名中
OrderFactory,LoginProxy,ResourceObserver

接口和實(shí)現(xiàn)類的命名規(guī)則:

  1. 對(duì)于Service和DAO,暴露接口,內(nèi)部實(shí)現(xiàn)類使用Impl后綴。
  2. 對(duì)于形容能力的接口,取對(duì)應(yīng)名詞作為實(shí)現(xiàn)類。 AbstractTranslator實(shí)現(xiàn)Translatable

枚舉類帶上Enum后綴,成員名稱大寫

Service/DAO層方法命名規(guī)約。

  1. 獲取單個(gè)對(duì)象的方法用get做前綴。
  2. 獲取多個(gè)對(duì)象的方法法用list做前綴。
  3. 獲取統(tǒng)計(jì)值方法用count做前綴。
  4. 插入的方法用save或insert做前綴。
  5. 刪除的方法用remove或delete做前綴。
  6. 修改的方法用update做前綴。

領(lǐng)域模型命名規(guī)約

  1. 數(shù)據(jù)對(duì)象:xxxDO,xxx為表名。
  2. 數(shù)據(jù)傳輸對(duì)象:xxxDTO,xxx為業(yè)務(wù)領(lǐng)域相關(guān)名稱。
  3. 展示對(duì)象:xxxVO,xxx一般為網(wǎng)頁(yè)名稱。
  4. POJP是DO/DTO/BO/VO的統(tǒng)稱

常量定義

  1. 不允許出現(xiàn)魔法值(即未經(jīng)定義的常量)直接出現(xiàn)在代碼中。
  2. 常量應(yīng)用分層
  1. 跨應(yīng)用共享常量:放置在二方庫(kù)中。
  2. 應(yīng)用內(nèi)共享常量:放置在一方庫(kù)的modules的constant目錄下。
  3. 子工程內(nèi)部共享常量:在當(dāng)前子工程的constant目錄下。
  4. 包內(nèi)共享常量:放在包內(nèi)單獨(dú)的constant目錄下。
  5. 類內(nèi)共享常量:類內(nèi)部private static final。
    3.如果變量值僅在一個(gè)范圍內(nèi)變化用Enum類。如果帶有名稱之外的延伸屬性,必須使用Enum類
//正例:
public DayEnum{MONDAY(1),TUESDAY(2),WEDNESDAY(3),THURSDAY(4),FRIDAY(5),SATURDAY(6),SUNDAY(7);}

格式規(guī)約

  1. 大括號(hào)使用約定:
//正例
public static void main(String[] args) {
    // 縮進(jìn) 4 個(gè)空格
    String say = "hello";
    // 運(yùn)算符的左右必須有一個(gè)空格
    int flag = 0;
    // 關(guān)鍵詞 if 與括號(hào)之間必須有一個(gè)空格,括號(hào)內(nèi)的 f 與左括號(hào), 0 與右括號(hào)不需要空格
    if (flag == 0) {
        System.out.println(say);
    }
    // 左大括號(hào)前加空格且不換行;左大括號(hào)后換行
    if (flag == 1) {
        System.out.println("world");
    // 右大括號(hào)前換行,右大括號(hào)后有 else,不用換行
    } else {
        System.out.println("ok");
    // 在右大括號(hào)后直接結(jié)束,則必須換行
    }
}
  1. 單行字符不超過120個(gè),換行規(guī)則如下:
  1. 第二行縮進(jìn)4個(gè)空格,第三行不再繼續(xù)縮進(jìn)。
  2. 運(yùn)算符、方法調(diào)用符與下文一起換行。
  3. 逗號(hào)后換行。
//正例
dataset.add("a", "b", "c")...
    .add("a", "b", "c")...
    "d");
  1. 逗號(hào)后必須要有一個(gè)空格。
  2. IDE的text file encoding設(shè)置為UTF-8,換行符用Unix格式。
  3. 方法體內(nèi)不同的業(yè)務(wù)邏輯語(yǔ)句組之間插入一個(gè)空格。

OOP規(guī)約

  1. 避免使用對(duì)象來訪問靜態(tài)變量或方法,直接用類名
    BeanUtils.copyProperties(model)
  2. 覆蓋方法必須加@Override注解。
  3. 接口被調(diào)用時(shí),不能改動(dòng),過時(shí)加@Deprecated注解。
  4. 不能使用過時(shí)的類或方法。
  5. 使用常量或確定有值的對(duì)象來調(diào)用equals,或使用Objects.equals(a,b)方法。
  6. 所有包裝類對(duì)象之間值的比較全部使用equals方法。
  7. 關(guān)于基本數(shù)據(jù)類型與包裝數(shù)據(jù)類型的使用標(biāo)準(zhǔn)如下:
  1. 所有的POJO類屬性必須使用包裝數(shù)據(jù)類型。
    Long id,public Integer count()
  2. RPC方法的返回值和參數(shù)使用包裝數(shù)據(jù)類型。
  3. 所有局部變量使用基本數(shù)據(jù)類型。
  1. POJO類不要設(shè)定任何屬性默認(rèn)值
  2. 序列化類新增屬性時(shí),不要修改serialVersionUID
  3. 構(gòu)造方法禁止加入任何業(yè)務(wù)邏輯,初始化邏輯放在init方法中。
  4. POJO類必須寫toString方法,注意繼承類時(shí)調(diào)用super.toString()
  5. 類內(nèi)定義順序依次是:公有方法或保護(hù)方法 > 私有方法 > getter/setter
  6. getter/setter方法中不要增加業(yè)務(wù)邏輯。
  7. 類成員與方法訪問控制從嚴(yán):
  1. 如果不允許外部通過new來創(chuàng)建對(duì)象,構(gòu)造方法必須為private
  2. 工具類不允許有publicdefault構(gòu)造方法。
  3. 類非static成員變量并且與子類共享,必須是protected
  4. 類非static成員變量并且僅在本類使用,必須是private
  5. static成員變量?jī)H在本類使用,必須為private
  6. 若是static成員變量,必須考慮是否為final
  7. 類成員方法僅供類內(nèi)部調(diào)用,必須是private
  8. 類成員方法只對(duì)繼承類公開,那么限制為protected

集合處理

  1. 關(guān)于hashCodeequals的處理,遵循如下規(guī)則:
  1. 只要重寫equals,則必須重寫hashCode
  2. 如果需要用Set存儲(chǔ)的對(duì)象,必須重寫兩個(gè)方法。
  3. 如果自定義對(duì)象作為Map的鍵,必須重寫兩個(gè)方法。
  1. 集合轉(zhuǎn)數(shù)組使用集合的toArray(T[] array),傳入類型相同大小相同的數(shù)組。
    String[] strArray = new String[list.size()];
    strArray = list.toArray(strArray);
  1. 使用工具類Arrays.asList()把數(shù)組轉(zhuǎn)換成集合時(shí),不能使用修改集合的方法
    說明:體現(xiàn)了適配器模式,只是轉(zhuǎn)換接口,后臺(tái)的數(shù)據(jù)仍是數(shù)組。
  2. Comparator要滿足如下三個(gè)條件,不然Arrays.sortCollections.sort會(huì)報(bào)異常。
  1. x,y的比較結(jié)果和y,x的比較結(jié)果相反。
  2. x>y,y>z,則x>z。
  3. x=y,則x,z比較結(jié)果和y,z比較結(jié)果相同。
  1. 使用entrySet遍歷Map
  2. 高度注意Map類集合能不能存儲(chǔ)null值的情況,如下表格:
    |集合類|Key|Value|Super|說明|
    |---|
    |Hashtable|不允許null|不允許null|Dictionary|線程安全|
    |ConcurrentHashMap|不允許null|不允許null|AbstractMap|分段鎖技術(shù)|
    |TreeMap|不允許null|允許null|AbstractMap|線程不安全|
    |HashMap|允許null|允許null|AbstractMap|線程不安全|
  3. 利用Set來去重元素。

并發(fā)處理

  1. 獲取單例對(duì)象需要保證線程安全,其中的方法也要保證。
    說明:資源驅(qū)動(dòng)類、工具類、單例工廠都需要注意

  2. 創(chuàng)建線程或線程池時(shí)請(qǐng)指定有意義的線程名稱,方便出錯(cuò)時(shí)回溯。

public class TimerTaskThread extends Thread {
public TimerTaskThread() {
super.setName("TimerTaskThread"); ...
}
  1. 線程資源必須通過線程池提供,不允許在應(yīng)用中自行顯式創(chuàng)建線程。
    說明:使用線程池的好處是減少在創(chuàng)建和銷毀線程上所花的時(shí)間以及系統(tǒng)資源的開銷,解決資源不足的問題。如果不使用線程池,有可能造成系統(tǒng)創(chuàng)建大量同類線程而導(dǎo)致消耗完內(nèi)存或者“過度切換”的問題。

  2. 線程池不允許使用Executors去創(chuàng)建,而是通過ThreadPoolExecutor的方式,以更明確線程池運(yùn)行規(guī)則。

  3. SimpleDateFormat是線程不安全的類,不要定義為static,或使用DateUtils工具類

private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
    @Override
    protected DateFormat initialValue(){
        return new SimpleDateFormat("yyyy-MM-dd");
    }
}
  1. 高并發(fā)時(shí),同步調(diào)用應(yīng)該去考量鎖的性能損耗。無鎖數(shù)據(jù)結(jié)構(gòu)>鎖區(qū)塊>方法鎖>對(duì)象鎖>類鎖

  2. 對(duì)多個(gè)資源、數(shù)據(jù)庫(kù)表、對(duì)象同時(shí)加鎖時(shí),需要保持一致的加鎖順序,避免死鎖。

  3. 并發(fā)修改同一記錄時(shí),避免更新丟失,需要加鎖。要么在應(yīng)用加鎖,要么在緩存加鎖,要么在數(shù)據(jù)庫(kù)層使用樂觀鎖,使用version作為更新依據(jù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容