編程規(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ī)則:
- 對(duì)于Service和DAO,暴露接口,內(nèi)部實(shí)現(xiàn)類使用Impl后綴。
- 對(duì)于形容能力的接口,取對(duì)應(yīng)名詞作為實(shí)現(xiàn)類。
AbstractTranslator
實(shí)現(xiàn)Translatable
枚舉類帶上Enum后綴,成員名稱大寫。
Service/DAO層方法命名規(guī)約。
- 獲取單個(gè)對(duì)象的方法用get做前綴。
- 獲取多個(gè)對(duì)象的方法法用list做前綴。
- 獲取統(tǒng)計(jì)值方法用count做前綴。
- 插入的方法用save或insert做前綴。
- 刪除的方法用remove或delete做前綴。
- 修改的方法用update做前綴。
領(lǐng)域模型命名規(guī)約
- 數(shù)據(jù)對(duì)象:xxxDO,xxx為表名。
- 數(shù)據(jù)傳輸對(duì)象:xxxDTO,xxx為業(yè)務(wù)領(lǐng)域相關(guān)名稱。
- 展示對(duì)象:xxxVO,xxx一般為網(wǎng)頁(yè)名稱。
- POJP是DO/DTO/BO/VO的統(tǒng)稱
常量定義
- 不允許出現(xiàn)魔法值(即未經(jīng)定義的常量)直接出現(xiàn)在代碼中。
- 常量應(yīng)用分層
- 跨應(yīng)用共享常量:放置在二方庫(kù)中。
- 應(yīng)用內(nèi)共享常量:放置在一方庫(kù)的modules的constant目錄下。
- 子工程內(nèi)部共享常量:在當(dāng)前子工程的constant目錄下。
- 包內(nèi)共享常量:放在包內(nèi)單獨(dú)的constant目錄下。
- 類內(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ī)約
- 大括號(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é)束,則必須換行
}
}
- 單行字符不超過120個(gè),換行規(guī)則如下:
- 第二行縮進(jìn)4個(gè)空格,第三行不再繼續(xù)縮進(jìn)。
- 運(yùn)算符、方法調(diào)用符與下文一起換行。
- 逗號(hào)后換行。
//正例
dataset.add("a", "b", "c")...
.add("a", "b", "c")...
"d");
- 逗號(hào)后必須要有一個(gè)空格。
- IDE的text file encoding設(shè)置為UTF-8,換行符用Unix格式。
- 方法體內(nèi)不同的業(yè)務(wù)邏輯語(yǔ)句組之間插入一個(gè)空格。
OOP規(guī)約
- 避免使用對(duì)象來訪問靜態(tài)變量或方法,直接用類名。
BeanUtils.copyProperties(model)
- 覆蓋方法必須加
@Override
注解。 - 接口被調(diào)用時(shí),不能改動(dòng),過時(shí)加
@Deprecated
注解。 - 不能使用過時(shí)的類或方法。
- 使用常量或確定有值的對(duì)象來調(diào)用
equals
,或使用Objects.equals(a,b)
方法。 - 所有包裝類對(duì)象之間值的比較全部使用
equals
方法。 - 關(guān)于基本數(shù)據(jù)類型與包裝數(shù)據(jù)類型的使用標(biāo)準(zhǔn)如下:
- 所有的POJO類屬性必須使用包裝數(shù)據(jù)類型。
Long id
,public Integer count()
- RPC方法的返回值和參數(shù)使用包裝數(shù)據(jù)類型。
- 所有局部變量使用基本數(shù)據(jù)類型。
- POJO類不要設(shè)定任何屬性默認(rèn)值。
- 序列化類新增屬性時(shí),不要修改
serialVersionUID
。 - 構(gòu)造方法禁止加入任何業(yè)務(wù)邏輯,初始化邏輯放在init方法中。
- POJO類必須寫
toString
方法,注意繼承類時(shí)調(diào)用super.toString()
。 - 類內(nèi)定義順序依次是:公有方法或保護(hù)方法 > 私有方法 >
getter
/setter
-
getter
/setter
方法中不要增加業(yè)務(wù)邏輯。 - 類成員與方法訪問控制從嚴(yán):
- 如果不允許外部通過
new
來創(chuàng)建對(duì)象,構(gòu)造方法必須為private
。 - 工具類不允許有
public
或default
構(gòu)造方法。 - 類非
static
成員變量并且與子類共享,必須是protected
。 - 類非
static
成員變量并且僅在本類使用,必須是private
。 - 類
static
成員變量?jī)H在本類使用,必須為private
- 若是
static
成員變量,必須考慮是否為final
。 - 類成員方法僅供類內(nèi)部調(diào)用,必須是
private
。 - 類成員方法只對(duì)繼承類公開,那么限制為
protected
。
集合處理
- 關(guān)于
hashCode
和equals
的處理,遵循如下規(guī)則:
- 只要重寫
equals
,則必須重寫hashCode
。 - 如果需要用
Set
存儲(chǔ)的對(duì)象,必須重寫兩個(gè)方法。 - 如果自定義對(duì)象作為
Map
的鍵,必須重寫兩個(gè)方法。
- 集合轉(zhuǎn)數(shù)組使用集合的
toArray(T[] array)
,傳入類型相同,大小相同的數(shù)組。
String[] strArray = new String[list.size()];
strArray = list.toArray(strArray);
- 使用工具類
Arrays.asList()
把數(shù)組轉(zhuǎn)換成集合時(shí),不能使用修改集合的方法
說明:體現(xiàn)了適配器模式,只是轉(zhuǎn)換接口,后臺(tái)的數(shù)據(jù)仍是數(shù)組。 -
Comparator
要滿足如下三個(gè)條件,不然Arrays.sort
或Collections.sort
會(huì)報(bào)異常。
- x,y的比較結(jié)果和y,x的比較結(jié)果相反。
- x>y,y>z,則x>z。
- x=y,則x,z比較結(jié)果和y,z比較結(jié)果相同。
- 使用
entrySet
遍歷Map
。 - 高度注意
Map
類集合能不能存儲(chǔ)null
值的情況,如下表格:
|集合類|Key|Value|Super|說明|
|---|
|Hashtable
|不允許null
|不允許null
|Dictionary
|線程安全|
|ConcurrentHashMap
|不允許null
|不允許null
|AbstractMap
|分段鎖技術(shù)|
|TreeMap
|不允許null
|允許null
|AbstractMap
|線程不安全|
|HashMap
|允許null
|允許null
|AbstractMap
|線程不安全| - 利用
Set
來去重元素。
并發(fā)處理
獲取單例對(duì)象需要保證線程安全,其中的方法也要保證。
說明:資源驅(qū)動(dòng)類、工具類、單例工廠都需要注意創(chuàng)建線程或線程池時(shí)請(qǐng)指定有意義的線程名稱,方便出錯(cuò)時(shí)回溯。
public class TimerTaskThread extends Thread {
public TimerTaskThread() {
super.setName("TimerTaskThread"); ...
}
線程資源必須通過線程池提供,不允許在應(yīng)用中自行顯式創(chuàng)建線程。
說明:使用線程池的好處是減少在創(chuàng)建和銷毀線程上所花的時(shí)間以及系統(tǒng)資源的開銷,解決資源不足的問題。如果不使用線程池,有可能造成系統(tǒng)創(chuàng)建大量同類線程而導(dǎo)致消耗完內(nèi)存或者“過度切換”的問題。線程池不允許使用
Executors
去創(chuàng)建,而是通過ThreadPoolExecutor
的方式,以更明確線程池運(yùn)行規(guī)則。SimpleDateFormat
是線程不安全的類,不要定義為static
,或使用DateUtils
工具類
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue(){
return new SimpleDateFormat("yyyy-MM-dd");
}
}
高并發(fā)時(shí),同步調(diào)用應(yīng)該去考量鎖的性能損耗。無鎖數(shù)據(jù)結(jié)構(gòu)>鎖區(qū)塊>方法鎖>對(duì)象鎖>類鎖
對(duì)多個(gè)資源、數(shù)據(jù)庫(kù)表、對(duì)象同時(shí)加鎖時(shí),需要保持一致的加鎖順序,避免死鎖。
并發(fā)修改同一記錄時(shí),避免更新丟失,需要加鎖。要么在應(yīng)用加鎖,要么在緩存加鎖,要么在數(shù)據(jù)庫(kù)層使用樂觀鎖,使用version作為更新依據(jù)。